Auto merge of #117135 - matthiaskrgr:rollup-zdh18i6, r=matthiaskrgr

Rollup of 8 pull requests

Successful merges:

 - #116094 (Introduce `-C instrument-coverage=branch` to gate branch coverage)
 - #116396 (Migrate diagnostics in `rustc_hir_analysis/src/coherence/orphan.rs`)
 - #116714 (Derive `Ord`, `PartialOrd` and `Hash` for `SocketAddr*`)
 - #116792 (Avoid unnecessary renumbering during borrowck)
 - #116841 (Suggest unwrap/expect for let binding type mismatch)
 - #116943 (Add target features for LoongArch)
 - #117010 (Add method to convert internal to stable constructs)
 - #117127 (Remove `#[allow(incomplete_features)]` from RPITIT/AFIT tests)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-10-24 19:32:19 +00:00
commit 151256bd4b
75 changed files with 1035 additions and 435 deletions

View File

@ -4525,6 +4525,7 @@ dependencies = [
"rustc_middle",
"rustc_span",
"rustc_target",
"scoped-tls",
"stable_mir",
"tracing",
]

View File

@ -81,6 +81,10 @@ impl<'a, 'tcx> MutVisitor<'tcx> for RegionRenumberer<'a, 'tcx> {
#[instrument(skip(self), level = "debug")]
fn visit_ty(&mut self, ty: &mut Ty<'tcx>, ty_context: TyContext) {
if matches!(ty_context, TyContext::ReturnTy(_)) {
// We will renumber the return ty when called again with `TyContext::LocalDecl`
return;
}
*ty = self.renumber_regions(*ty, || RegionCtxt::TyContext(ty_context));
debug!(?ty);

View File

@ -342,6 +342,19 @@ const CSKY_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
("hard-float-abi", Some(sym::csky_target_feature)),
// tidy-alphabetical-end
];
const LOONGARCH_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
// tidy-alphabetical-start
("d", Some(sym::loongarch_target_feature)),
("f", Some(sym::loongarch_target_feature)),
("lasx", Some(sym::loongarch_target_feature)),
("lbt", Some(sym::loongarch_target_feature)),
("lsx", Some(sym::loongarch_target_feature)),
("lvz", Some(sym::loongarch_target_feature)),
("ual", Some(sym::loongarch_target_feature)),
// tidy-alphabetical-end
];
/// When rustdoc is running, provide a list of all known features so that all their respective
/// primitives may be documented.
///
@ -358,6 +371,7 @@ pub fn all_known_features() -> impl Iterator<Item = (&'static str, Option<Symbol
.chain(WASM_ALLOWED_FEATURES.iter())
.chain(BPF_ALLOWED_FEATURES.iter())
.chain(CSKY_ALLOWED_FEATURES)
.chain(LOONGARCH_ALLOWED_FEATURES)
.cloned()
}
@ -373,6 +387,7 @@ pub fn supported_target_features(sess: &Session) -> &'static [(&'static str, Opt
"wasm32" | "wasm64" => WASM_ALLOWED_FEATURES,
"bpf" => BPF_ALLOWED_FEATURES,
"csky" => CSKY_ALLOWED_FEATURES,
"loongarch64" => LOONGARCH_ALLOWED_FEATURES,
_ => &[],
}
}
@ -445,6 +460,7 @@ pub fn from_target_feature(
Some(sym::bpf_target_feature) => rust_features.bpf_target_feature,
Some(sym::aarch64_ver_target_feature) => rust_features.aarch64_ver_target_feature,
Some(sym::csky_target_feature) => rust_features.csky_target_feature,
Some(sym::loongarch_target_feature) => rust_features.loongarch_target_feature,
Some(name) => bug!("unknown target feature gate {}", name),
None => true,
};

View File

@ -288,6 +288,7 @@ declare_features! (
(unstable, csky_target_feature, "1.73.0", Some(44839), None),
(unstable, ermsb_target_feature, "1.49.0", Some(44839), None),
(unstable, hexagon_target_feature, "1.27.0", Some(44839), None),
(unstable, loongarch_target_feature, "1.73.0", Some(44839), None),
(unstable, mips_target_feature, "1.27.0", Some(44839), None),
(unstable, powerpc_target_feature, "1.27.0", Some(44839), None),
(unstable, riscv_target_feature, "1.45.0", Some(44839), None),

View File

@ -72,6 +72,12 @@ hir_analysis_copy_impl_on_type_with_dtor =
the trait `Copy` cannot be implemented for this type; the type has a destructor
.label = `Copy` not allowed on types with destructors
hir_analysis_cross_crate_traits = cross-crate traits with a default impl, like `{$traits}`, can only be implemented for a struct/enum type, not `{$self_ty}`
.label = can't implement cross-crate trait with a default impl for non-struct/enum type
hir_analysis_cross_crate_traits_defined = cross-crate traits with a default impl, like `{$traits}`, can only be implemented for a struct/enum type defined in the current crate
.label = can't implement cross-crate trait for type in another crate
hir_analysis_dispatch_from_dyn_multi = implementing the `DispatchFromDyn` trait requires multiple coercions
.note = the trait `DispatchFromDyn` may only be implemented for a coercion between structures with a single field being coerced
.coercions_note = currently, {$number} fields need coercions: {$coercions}
@ -237,6 +243,28 @@ hir_analysis_must_implement_not_function_span_note = required by this annotation
hir_analysis_must_implement_one_of_attribute = the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args
hir_analysis_only_current_traits_arbitrary = only traits defined in the current crate can be implemented for arbitrary types
hir_analysis_only_current_traits_foreign = this is not defined in the current crate because this is a foreign trait
hir_analysis_only_current_traits_label = impl doesn't use only types from inside the current crate
hir_analysis_only_current_traits_name = this is not defined in the current crate because {$name} are always foreign
hir_analysis_only_current_traits_note = define and implement a trait or new type instead
hir_analysis_only_current_traits_opaque = type alias impl trait is treated as if it were foreign, because its hidden type could be from a foreign crate
hir_analysis_only_current_traits_outside = only traits defined in the current crate can be implemented for types defined outside of the crate
hir_analysis_only_current_traits_pointer = `{$pointer}` is not defined in the current crate because raw pointers are always foreign
hir_analysis_only_current_traits_pointer_sugg = consider introducing a new wrapper type
hir_analysis_only_current_traits_primitive = only traits defined in the current crate can be implemented for primitive types
hir_analysis_only_current_traits_ty = `{$ty}` is not defined in the current crate
hir_analysis_paren_sugar_attribute = the `#[rustc_paren_sugar]` attribute is a temporary means of controlling which traits can use parenthetical notation
.help = add `#![feature(unboxed_closures)]` to the crate attributes to use it
@ -326,6 +354,9 @@ hir_analysis_trait_object_declared_with_no_traits =
at least one trait is required for an object type
.alias_span = this alias does not contain a trait
hir_analysis_traits_with_defualt_impl = traits with a default impl, like `{$traits}`, cannot be implemented for {$problematic_kind} `{$self_ty}`
.note = a trait object implements `{$traits}` if and only if `{$traits}` is one of the trait object's trait bounds
hir_analysis_transparent_enum_variant = transparent enum needs exactly one variant, but has {$number}
.label = needs exactly one variant, but has {$number}
.many_label = too many variants in `{$path}`
@ -339,6 +370,16 @@ hir_analysis_transparent_non_zero_sized_enum = the variant of a transparent {$de
.label = needs at most one field with non-trivial size or alignment, but has {$field_count}
.labels = this field has non-zero size or requires alignment
hir_analysis_ty_param_first_local = type parameter `{$param_ty}` must be covered by another type when it appears before the first local type (`{$local_type}`)
.label = type parameter `{$param_ty}` must be covered by another type when it appears before the first local type (`{$local_type}`)
.note = implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type
.case_note = in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last
hir_analysis_ty_param_some = type parameter `{$param_ty}` must be used as the type parameter for some local type (e.g., `MyStruct<{$param_ty}>`)
.label = type parameter `{$param_ty}` must be used as the type parameter for some local type
.note = implementing a foreign trait is only possible if at least one of the types for which it is implemented is local
.only_note = only traits defined in the current crate can be implemented for a type parameter
hir_analysis_type_of = {$type_of}
hir_analysis_typeof_reserved_keyword_used =

View File

@ -2,8 +2,7 @@
//! crate or pertains to a type defined in this crate.
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{struct_span_err, DelayDm};
use rustc_errors::{Diagnostic, ErrorGuaranteed};
use rustc_errors::{DelayDm, ErrorGuaranteed};
use rustc_hir as hir;
use rustc_middle::ty::util::CheckRegions;
use rustc_middle::ty::GenericArgs;
@ -17,6 +16,8 @@ use rustc_span::Span;
use rustc_trait_selection::traits;
use std::ops::ControlFlow;
use crate::errors;
#[instrument(skip(tcx), level = "debug")]
pub(crate) fn orphan_check_impl(
tcx: TyCtxt<'_>,
@ -259,49 +260,30 @@ fn do_orphan_check_impl<'tcx>(
match local_impl {
LocalImpl::Allow => {}
LocalImpl::Disallow { problematic_kind } => {
let msg = format!(
"traits with a default impl, like `{trait}`, \
cannot be implemented for {problematic_kind} `{self_ty}`",
trait = tcx.def_path_str(trait_def_id),
);
let label = format!(
"a trait object implements `{trait}` if and only if `{trait}` \
is one of the trait object's trait bounds",
trait = tcx.def_path_str(trait_def_id),
);
let sp = tcx.def_span(def_id);
let reported =
struct_span_err!(tcx.sess, sp, E0321, "{}", msg).note(label).emit();
return Err(reported);
return Err(tcx.sess.emit_err(errors::TraitsWithDefaultImpl {
span: tcx.def_span(def_id),
traits: tcx.def_path_str(trait_def_id),
problematic_kind,
self_ty,
}));
}
}
} else {
if let Some((msg, label)) = match nonlocal_impl {
NonlocalImpl::Allow => None,
NonlocalImpl::DisallowBecauseNonlocal => Some((
format!(
"cross-crate traits with a default impl, like `{}`, \
can only be implemented for a struct/enum type \
defined in the current crate",
tcx.def_path_str(trait_def_id)
),
"can't implement cross-crate trait for type in another crate",
)),
NonlocalImpl::DisallowOther => Some((
format!(
"cross-crate traits with a default impl, like `{}`, can \
only be implemented for a struct/enum type, not `{}`",
tcx.def_path_str(trait_def_id),
self_ty
),
"can't implement cross-crate trait with a default impl for \
non-struct/enum type",
)),
} {
let sp = tcx.def_span(def_id);
let reported =
struct_span_err!(tcx.sess, sp, E0321, "{}", msg).span_label(sp, label).emit();
return Err(reported);
match nonlocal_impl {
NonlocalImpl::Allow => {}
NonlocalImpl::DisallowBecauseNonlocal => {
return Err(tcx.sess.emit_err(errors::CrossCrateTraitsDefined {
span: tcx.def_span(def_id),
traits: tcx.def_path_str(trait_def_id),
}));
}
NonlocalImpl::DisallowOther => {
return Err(tcx.sess.emit_err(errors::CrossCrateTraits {
span: tcx.def_span(def_id),
traits: tcx.def_path_str(trait_def_id),
self_ty,
}));
}
}
}
}
@ -322,19 +304,18 @@ fn emit_orphan_check_error<'tcx>(
let self_ty = trait_ref.self_ty();
Err(match err {
traits::OrphanCheckErr::NonLocalInputType(tys) => {
let msg = match self_ty.kind() {
ty::Adt(..) => "can be implemented for types defined outside of the crate",
_ if self_ty.is_primitive() => "can be implemented for primitive types",
_ => "can be implemented for arbitrary types",
};
let mut err = struct_span_err!(
tcx.sess,
sp,
E0117,
"only traits defined in the current crate {msg}"
);
err.span_label(sp, "impl doesn't use only types from inside the current crate");
let (mut opaque, mut foreign, mut name, mut pointer, mut ty_diag) =
(Vec::new(), Vec::new(), Vec::new(), Vec::new(), Vec::new());
let mut sugg = None;
for &(mut ty, is_target_ty) in &tys {
let span = if is_target_ty {
// Point at `D<A>` in `impl<A, B> for C<B> in D<A>`
self_ty_span
} else {
// Point at `C<B>` in `impl<A, B> for C<B> in D<A>`
trait_span
};
ty = tcx.erase_regions(ty);
ty = match ty.kind() {
// Remove the type arguments from the output, as they are not relevant.
@ -345,50 +326,103 @@ fn emit_orphan_check_error<'tcx>(
ty::Adt(def, _) => Ty::new_adt(tcx, *def, ty::List::empty()),
_ => ty,
};
let msg = |ty: &str, postfix: &str| {
format!("{ty} is not defined in the current crate{postfix}")
};
let this = |name: &str| {
if !trait_ref.def_id.is_local() && !is_target_ty {
msg("this", " because this is a foreign trait")
fn push_to_foreign_or_name<'tcx>(
is_foreign: bool,
foreign: &mut Vec<errors::OnlyCurrentTraitsForeign>,
name: &mut Vec<errors::OnlyCurrentTraitsName<'tcx>>,
span: Span,
sname: &'tcx str,
) {
if is_foreign {
foreign.push(errors::OnlyCurrentTraitsForeign { span })
} else {
msg("this", &format!(" because {name} are always foreign"))
name.push(errors::OnlyCurrentTraitsName { span, name: sname });
}
}
let is_foreign = !trait_ref.def_id.is_local() && !is_target_ty;
match &ty.kind() {
ty::Slice(_) => {
push_to_foreign_or_name(
is_foreign,
&mut foreign,
&mut name,
span,
"slices",
);
}
ty::Array(..) => {
push_to_foreign_or_name(
is_foreign,
&mut foreign,
&mut name,
span,
"arrays",
);
}
ty::Tuple(..) => {
push_to_foreign_or_name(
is_foreign,
&mut foreign,
&mut name,
span,
"tuples",
);
}
};
let msg = match &ty.kind() {
ty::Slice(_) => this("slices"),
ty::Array(..) => this("arrays"),
ty::Tuple(..) => this("tuples"),
ty::Alias(ty::Opaque, ..) => {
"type alias impl trait is treated as if it were foreign, \
because its hidden type could be from a foreign crate"
.to_string()
opaque.push(errors::OnlyCurrentTraitsOpaque { span })
}
ty::RawPtr(ptr_ty) => {
emit_newtype_suggestion_for_raw_ptr(
full_impl_span,
self_ty,
self_ty_span,
ptr_ty,
&mut err,
);
msg(&format!("`{ty}`"), " because raw pointers are always foreign")
if !self_ty.has_param() {
let mut_key = ptr_ty.mutbl.prefix_str();
sugg = Some(errors::OnlyCurrentTraitsPointerSugg {
wrapper_span: self_ty_span,
struct_span: full_impl_span.shrink_to_lo(),
mut_key,
ptr_ty: ptr_ty.ty,
});
}
pointer.push(errors::OnlyCurrentTraitsPointer { span, pointer: ty });
}
_ => msg(&format!("`{ty}`"), ""),
};
if is_target_ty {
// Point at `D<A>` in `impl<A, B> for C<B> in D<A>`
err.span_label(self_ty_span, msg);
} else {
// Point at `C<B>` in `impl<A, B> for C<B> in D<A>`
err.span_label(trait_span, msg);
_ => ty_diag.push(errors::OnlyCurrentTraitsTy { span, ty }),
}
}
err.note("define and implement a trait or new type instead");
err.emit()
let err_struct = match self_ty.kind() {
ty::Adt(..) => errors::OnlyCurrentTraits::Outside {
span: sp,
note: (),
opaque,
foreign,
name,
pointer,
ty: ty_diag,
sugg,
},
_ if self_ty.is_primitive() => errors::OnlyCurrentTraits::Primitive {
span: sp,
note: (),
opaque,
foreign,
name,
pointer,
ty: ty_diag,
sugg,
},
_ => errors::OnlyCurrentTraits::Arbitrary {
span: sp,
note: (),
opaque,
foreign,
name,
pointer,
ty: ty_diag,
sugg,
},
};
tcx.sess.emit_err(err_struct)
}
traits::OrphanCheckErr::UncoveredTy(param_ty, local_type) => {
let mut sp = sp;
@ -399,85 +433,18 @@ fn emit_orphan_check_error<'tcx>(
}
match local_type {
Some(local_type) => struct_span_err!(
tcx.sess,
sp,
E0210,
"type parameter `{}` must be covered by another type \
when it appears before the first local type (`{}`)",
Some(local_type) => tcx.sess.emit_err(errors::TyParamFirstLocal {
span: sp,
note: (),
param_ty,
local_type
)
.span_label(
sp,
format!(
"type parameter `{param_ty}` must be covered by another type \
when it appears before the first local type (`{local_type}`)"
),
)
.note(
"implementing a foreign trait is only possible if at \
least one of the types for which it is implemented is local, \
and no uncovered type parameters appear before that first \
local type",
)
.note(
"in this case, 'before' refers to the following order: \
`impl<..> ForeignTrait<T1, ..., Tn> for T0`, \
where `T0` is the first and `Tn` is the last",
)
.emit(),
None => struct_span_err!(
tcx.sess,
sp,
E0210,
"type parameter `{}` must be used as the type parameter for some \
local type (e.g., `MyStruct<{}>`)",
param_ty,
param_ty
)
.span_label(
sp,
format!(
"type parameter `{param_ty}` must be used as the type parameter for some \
local type",
),
)
.note(
"implementing a foreign trait is only possible if at \
least one of the types for which it is implemented is local",
)
.note(
"only traits defined in the current crate can be \
implemented for a type parameter",
)
.emit(),
local_type,
}),
None => tcx.sess.emit_err(errors::TyParamSome { span: sp, note: (), param_ty }),
}
}
})
}
fn emit_newtype_suggestion_for_raw_ptr(
full_impl_span: Span,
self_ty: Ty<'_>,
self_ty_span: Span,
ptr_ty: &ty::TypeAndMut<'_>,
diag: &mut Diagnostic,
) {
if !self_ty.has_param() {
let mut_key = ptr_ty.mutbl.prefix_str();
let msg_sugg = "consider introducing a new wrapper type".to_owned();
let sugg = vec![
(
full_impl_span.shrink_to_lo(),
format!("struct WrapperType(*{}{});\n\n", mut_key, ptr_ty.ty),
),
(self_ty_span, "WrapperType".to_owned()),
];
diag.multipart_suggestion(msg_sugg, sugg, rustc_errors::Applicability::MaybeIncorrect);
}
}
/// Lint impls of auto traits if they are likely to have
/// unsound or surprising effects on auto impls.
fn lint_auto_trait_impl<'tcx>(

View File

@ -683,7 +683,6 @@ pub(crate) struct SIMDFFIHighlyExperimental {
}
#[derive(Diagnostic)]
pub enum ImplNotMarkedDefault {
#[diag(hir_analysis_impl_not_marked_default, code = "E0520")]
#[note]
@ -1159,3 +1158,174 @@ pub struct ImplForTyRequires {
pub trait_name: String,
pub ty: String,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_traits_with_defualt_impl, code = "E0321")]
#[note]
pub struct TraitsWithDefaultImpl<'a> {
#[primary_span]
pub span: Span,
pub traits: String,
pub problematic_kind: &'a str,
pub self_ty: Ty<'a>,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_cross_crate_traits, code = "E0321")]
pub struct CrossCrateTraits<'a> {
#[primary_span]
#[label]
pub span: Span,
pub traits: String,
pub self_ty: Ty<'a>,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_cross_crate_traits_defined, code = "E0321")]
pub struct CrossCrateTraitsDefined {
#[primary_span]
#[label]
pub span: Span,
pub traits: String,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_ty_param_first_local, code = "E0210")]
#[note]
pub struct TyParamFirstLocal<'a> {
#[primary_span]
#[label]
pub span: Span,
#[note(hir_analysis_case_note)]
pub note: (),
pub param_ty: Ty<'a>,
pub local_type: Ty<'a>,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_ty_param_some, code = "E0210")]
#[note]
pub struct TyParamSome<'a> {
#[primary_span]
#[label]
pub span: Span,
#[note(hir_analysis_only_note)]
pub note: (),
pub param_ty: Ty<'a>,
}
#[derive(Diagnostic)]
pub enum OnlyCurrentTraits<'a> {
#[diag(hir_analysis_only_current_traits_outside, code = "E0117")]
Outside {
#[primary_span]
#[label(hir_analysis_only_current_traits_label)]
span: Span,
#[note(hir_analysis_only_current_traits_note)]
note: (),
#[subdiagnostic]
opaque: Vec<OnlyCurrentTraitsOpaque>,
#[subdiagnostic]
foreign: Vec<OnlyCurrentTraitsForeign>,
#[subdiagnostic]
name: Vec<OnlyCurrentTraitsName<'a>>,
#[subdiagnostic]
pointer: Vec<OnlyCurrentTraitsPointer<'a>>,
#[subdiagnostic]
ty: Vec<OnlyCurrentTraitsTy<'a>>,
#[subdiagnostic]
sugg: Option<OnlyCurrentTraitsPointerSugg<'a>>,
},
#[diag(hir_analysis_only_current_traits_primitive, code = "E0117")]
Primitive {
#[primary_span]
#[label(hir_analysis_only_current_traits_label)]
span: Span,
#[note(hir_analysis_only_current_traits_note)]
note: (),
#[subdiagnostic]
opaque: Vec<OnlyCurrentTraitsOpaque>,
#[subdiagnostic]
foreign: Vec<OnlyCurrentTraitsForeign>,
#[subdiagnostic]
name: Vec<OnlyCurrentTraitsName<'a>>,
#[subdiagnostic]
pointer: Vec<OnlyCurrentTraitsPointer<'a>>,
#[subdiagnostic]
ty: Vec<OnlyCurrentTraitsTy<'a>>,
#[subdiagnostic]
sugg: Option<OnlyCurrentTraitsPointerSugg<'a>>,
},
#[diag(hir_analysis_only_current_traits_arbitrary, code = "E0117")]
Arbitrary {
#[primary_span]
#[label(hir_analysis_only_current_traits_label)]
span: Span,
#[note(hir_analysis_only_current_traits_note)]
note: (),
#[subdiagnostic]
opaque: Vec<OnlyCurrentTraitsOpaque>,
#[subdiagnostic]
foreign: Vec<OnlyCurrentTraitsForeign>,
#[subdiagnostic]
name: Vec<OnlyCurrentTraitsName<'a>>,
#[subdiagnostic]
pointer: Vec<OnlyCurrentTraitsPointer<'a>>,
#[subdiagnostic]
ty: Vec<OnlyCurrentTraitsTy<'a>>,
#[subdiagnostic]
sugg: Option<OnlyCurrentTraitsPointerSugg<'a>>,
},
}
#[derive(Subdiagnostic)]
#[label(hir_analysis_only_current_traits_opaque)]
pub struct OnlyCurrentTraitsOpaque {
#[primary_span]
pub span: Span,
}
#[derive(Subdiagnostic)]
#[label(hir_analysis_only_current_traits_foreign)]
pub struct OnlyCurrentTraitsForeign {
#[primary_span]
pub span: Span,
}
#[derive(Subdiagnostic)]
#[label(hir_analysis_only_current_traits_name)]
pub struct OnlyCurrentTraitsName<'a> {
#[primary_span]
pub span: Span,
pub name: &'a str,
}
#[derive(Subdiagnostic)]
#[label(hir_analysis_only_current_traits_pointer)]
pub struct OnlyCurrentTraitsPointer<'a> {
#[primary_span]
pub span: Span,
pub pointer: Ty<'a>,
}
#[derive(Subdiagnostic)]
#[label(hir_analysis_only_current_traits_ty)]
pub struct OnlyCurrentTraitsTy<'a> {
#[primary_span]
pub span: Span,
pub ty: Ty<'a>,
}
#[derive(Subdiagnostic)]
#[multipart_suggestion(
hir_analysis_only_current_traits_pointer_sugg,
applicability = "maybe-incorrect"
)]
pub struct OnlyCurrentTraitsPointerSugg<'a> {
#[suggestion_part(code = "WrapperType")]
pub wrapper_span: Span,
#[suggestion_part(code = "struct WrapperType(*{mut_key}{ptr_ty});\n\n")]
pub struct_span: Span,
pub mut_key: &'a str,
pub ptr_ty: Ty<'a>,
}

View File

@ -58,7 +58,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|| self.suggest_into(err, expr, expr_ty, expected)
|| self.suggest_floating_point_literal(err, expr, expected)
|| self.suggest_null_ptr_for_literal_zero_given_to_ptr_arg(err, expr, expected)
|| self.suggest_coercing_result_via_try_operator(err, expr, expected, expr_ty);
|| self.suggest_coercing_result_via_try_operator(err, expr, expected, expr_ty)
|| self.suggest_missing_unwrap_expect(err, expr, expected, expr_ty);
if !suggested {
self.note_source_of_type_mismatch_constraint(

View File

@ -6,6 +6,7 @@ use crate::method::probe::{IsSuggestion, Mode, ProbeScope};
use rustc_ast::util::parser::{ExprPrecedence, PREC_POSTFIX};
use rustc_errors::{Applicability, Diagnostic, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def::Res;
use rustc_hir::def::{CtorKind, CtorOf, DefKind};
use rustc_hir::lang_items::LangItem;
use rustc_hir::{
@ -1738,4 +1739,83 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// If the field is hygienic it must come from the same syntax context.
&& self.tcx.def_ident_span(field.did).unwrap().normalize_to_macros_2_0().eq_ctxt(span)
}
pub(crate) fn suggest_missing_unwrap_expect(
&self,
err: &mut Diagnostic,
expr: &hir::Expr<'tcx>,
expected: Ty<'tcx>,
found: Ty<'tcx>,
) -> bool {
let ty::Adt(adt, args) = found.kind() else { return false };
let ret_ty_matches = |diagnostic_item| {
if let Some(ret_ty) = self
.ret_coercion
.as_ref()
.map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty()))
&& let ty::Adt(kind, _) = ret_ty.kind()
&& self.tcx.get_diagnostic_item(diagnostic_item) == Some(kind.did())
{
true
} else {
false
}
};
// don't suggest anything like `Ok(ok_val).unwrap()` , `Some(some_val).unwrap()`,
// `None.unwrap()` etc.
let is_ctor = matches!(
expr.kind,
hir::ExprKind::Call(
hir::Expr {
kind: hir::ExprKind::Path(hir::QPath::Resolved(
None,
hir::Path { res: Res::Def(hir::def::DefKind::Ctor(_, _), _), .. },
)),
..
},
..,
) | hir::ExprKind::Path(hir::QPath::Resolved(
None,
hir::Path { res: Res::Def(hir::def::DefKind::Ctor(_, _), _), .. },
)),
);
let (article, kind, variant, sugg_operator) =
if self.tcx.is_diagnostic_item(sym::Result, adt.did()) {
("a", "Result", "Err", ret_ty_matches(sym::Result))
} else if self.tcx.is_diagnostic_item(sym::Option, adt.did()) {
("an", "Option", "None", ret_ty_matches(sym::Option))
} else {
return false;
};
if is_ctor || !self.can_coerce(args.type_at(0), expected) {
return false;
}
let (msg, sugg) = if sugg_operator {
(
format!(
"use the `?` operator to extract the `{found}` value, propagating \
{article} `{kind}::{variant}` value to the caller"
),
"?",
)
} else {
(
format!(
"consider using `{kind}::expect` to unwrap the `{found}` value, \
panicking if the value is {article} `{kind}::{variant}`"
),
".expect(\"REASON\")",
)
};
err.span_suggestion_verbose(
expr.span.shrink_to_hi(),
msg,
sugg,
Applicability::HasPlaceholders,
);
return true;
}
}

View File

@ -169,6 +169,9 @@ pub enum MirSpanview {
pub enum InstrumentCoverage {
/// Default `-C instrument-coverage` or `-C instrument-coverage=statement`
All,
/// Additionally, instrument branches and output branch coverage.
/// `-Zunstable-options -C instrument-coverage=branch`
Branch,
/// `-Zunstable-options -C instrument-coverage=except-unused-generics`
ExceptUnusedGenerics,
/// `-Zunstable-options -C instrument-coverage=except-unused-functions`
@ -2747,7 +2750,10 @@ pub fn build_session_options(
}
(Some(InstrumentCoverage::Off | InstrumentCoverage::All), _) => {}
(Some(_), _) if !unstable_opts.unstable_options => {
handler.early_error("`-C instrument-coverage=except-*` requires `-Z unstable-options`");
handler.early_error(
"`-C instrument-coverage=branch` and `-C instrument-coverage=except-*` \
require `-Z unstable-options`",
);
}
(None, None) => {}
(None, ic) => {

View File

@ -389,7 +389,7 @@ mod desc {
pub const parse_mir_spanview: &str = "`statement` (default), `terminator`, or `block`";
pub const parse_dump_mono_stats: &str = "`markdown` (default) or `json`";
pub const parse_instrument_coverage: &str =
"`all` (default), `except-unused-generics`, `except-unused-functions`, or `off`";
"`all` (default), `branch`, `except-unused-generics`, `except-unused-functions`, or `off`";
pub const parse_instrument_xray: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), or a comma separated list of settings: `always` or `never` (mutually exclusive), `ignore-loops`, `instruction-threshold=N`, `skip-entry`, `skip-exit`";
pub const parse_unpretty: &str = "`string` or `string=string`";
pub const parse_treat_err_as_bug: &str = "either no value or a non-negative number";
@ -931,6 +931,7 @@ mod parse {
*slot = Some(match v {
"all" => InstrumentCoverage::All,
"branch" => InstrumentCoverage::Branch,
"except-unused-generics" | "except_unused_generics" => {
InstrumentCoverage::ExceptUnusedGenerics
}
@ -1356,6 +1357,7 @@ options! {
reports (note, the compiler build config must include `profiler = true`); \
implies `-C symbol-mangling-version=v0`. Optional values are:
`=all` (implicit value)
`=branch`
`=except-unused-generics`
`=except-unused-functions`
`=off` (default)"),
@ -1597,6 +1599,7 @@ options! {
reports (note, the compiler build config must include `profiler = true`); \
implies `-C symbol-mangling-version=v0`. Optional values are:
`=all` (implicit value)
`=branch`
`=except-unused-generics`
`=except-unused-functions`
`=off` (default)"),

View File

@ -702,6 +702,10 @@ impl Session {
self.opts.cg.instrument_coverage() != InstrumentCoverage::Off
}
pub fn instrument_coverage_branch(&self) -> bool {
self.opts.cg.instrument_coverage() == InstrumentCoverage::Branch
}
pub fn instrument_coverage_except_unused_generics(&self) -> bool {
self.opts.cg.instrument_coverage() == InstrumentCoverage::ExceptUnusedGenerics
}

View File

@ -9,6 +9,7 @@ rustc_hir = { path = "../rustc_hir" }
rustc_middle = { path = "../rustc_middle" }
rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
scoped-tls = "1.0"
stable_mir = {path = "../stable_mir" }
tracing = "0.1"

View File

@ -3,7 +3,7 @@
//! For that, we define APIs that will temporarily be public to 3P that exposes rustc internal APIs
//! until stable MIR is complete.
use crate::rustc_smir::Tables;
use crate::rustc_smir::{Stable, Tables, TablesWrapper};
use rustc_data_structures::fx;
use rustc_data_structures::fx::FxIndexMap;
use rustc_middle::mir::interpret::AllocId;
@ -11,13 +11,24 @@ use rustc_middle::ty;
use rustc_middle::ty::TyCtxt;
use rustc_span::def_id::{CrateNum, DefId};
use rustc_span::Span;
use scoped_tls::scoped_thread_local;
use stable_mir::ty::IndexedVal;
use std::cell::Cell;
use std::cell::RefCell;
use std::fmt::Debug;
use std::hash::Hash;
use std::ops::Index;
mod internal;
pub fn stable<'tcx, S: Stable<'tcx>>(item: &S) -> S::T {
with_tables(|tables| item.stable(tables))
}
pub fn internal<'tcx, S: RustcInternal<'tcx>>(item: &S) -> S::T {
with_tables(|tables| item.internal(tables))
}
impl<'tcx> Index<stable_mir::DefId> for Tables<'tcx> {
type Output = DefId;
@ -125,18 +136,41 @@ pub fn crate_num(item: &stable_mir::Crate) -> CrateNum {
item.id.into()
}
// A thread local variable that stores a pointer to the tables mapping between TyCtxt
// datastructures and stable MIR datastructures
scoped_thread_local! (static TLV: Cell<*const ()>);
pub(crate) fn init<'tcx>(tables: &TablesWrapper<'tcx>, f: impl FnOnce()) {
assert!(!TLV.is_set());
let ptr = tables as *const _ as *const ();
TLV.set(&Cell::new(ptr), || {
f();
});
}
/// Loads the current context and calls a function with it.
/// Do not nest these, as that will ICE.
pub(crate) fn with_tables<'tcx, R>(f: impl FnOnce(&mut Tables<'tcx>) -> R) -> R {
assert!(TLV.is_set());
TLV.with(|tlv| {
let ptr = tlv.get();
assert!(!ptr.is_null());
let wrapper = ptr as *const TablesWrapper<'tcx>;
let mut tables = unsafe { (*wrapper).0.borrow_mut() };
f(&mut *tables)
})
}
pub fn run(tcx: TyCtxt<'_>, f: impl FnOnce()) {
stable_mir::run(
Tables {
tcx,
def_ids: IndexMap::default(),
alloc_ids: IndexMap::default(),
spans: IndexMap::default(),
types: vec![],
instances: IndexMap::default(),
},
f,
);
let tables = TablesWrapper(RefCell::new(Tables {
tcx,
def_ids: IndexMap::default(),
alloc_ids: IndexMap::default(),
spans: IndexMap::default(),
types: vec![],
instances: IndexMap::default(),
}));
stable_mir::run(&tables, || init(&tables, f));
}
#[macro_export]
@ -251,7 +285,7 @@ impl<K: PartialEq + Hash + Eq, V: Copy + Debug + PartialEq + IndexedVal> Index<V
/// Trait used to translate a stable construct to its rustc counterpart.
///
/// This is basically a mirror of [crate::rustc_smir::Stable].
pub(crate) trait RustcInternal<'tcx> {
pub trait RustcInternal<'tcx> {
type T;
fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T;
}

View File

@ -23,27 +23,31 @@ use stable_mir::ty::{
FloatTy, GenericParamDef, IntTy, LineInfo, Movability, RigidTy, Span, TyKind, UintTy,
};
use stable_mir::{self, opaque, Context, Filename};
use std::cell::RefCell;
use tracing::debug;
mod alloc;
mod builder;
impl<'tcx> Context for Tables<'tcx> {
impl<'tcx> Context for TablesWrapper<'tcx> {
fn local_crate(&self) -> stable_mir::Crate {
smir_crate(self.tcx, LOCAL_CRATE)
let tables = self.0.borrow();
smir_crate(tables.tcx, LOCAL_CRATE)
}
fn external_crates(&self) -> Vec<stable_mir::Crate> {
self.tcx.crates(()).iter().map(|crate_num| smir_crate(self.tcx, *crate_num)).collect()
let tables = self.0.borrow();
tables.tcx.crates(()).iter().map(|crate_num| smir_crate(tables.tcx, *crate_num)).collect()
}
fn find_crates(&self, name: &str) -> Vec<stable_mir::Crate> {
let tables = self.0.borrow();
let crates: Vec<stable_mir::Crate> = [LOCAL_CRATE]
.iter()
.chain(self.tcx.crates(()).iter())
.chain(tables.tcx.crates(()).iter())
.map(|crate_num| {
let crate_name = self.tcx.crate_name(*crate_num).to_string();
(name == crate_name).then(|| smir_crate(self.tcx, *crate_num))
let crate_name = tables.tcx.crate_name(*crate_num).to_string();
(name == crate_name).then(|| smir_crate(tables.tcx, *crate_num))
})
.into_iter()
.filter_map(|c| c)
@ -52,163 +56,197 @@ impl<'tcx> Context for Tables<'tcx> {
}
fn name_of_def_id(&self, def_id: stable_mir::DefId) -> String {
self.tcx.def_path_str(self[def_id])
let tables = self.0.borrow();
tables.tcx.def_path_str(tables[def_id])
}
fn span_to_string(&self, span: stable_mir::ty::Span) -> String {
self.tcx.sess.source_map().span_to_diagnostic_string(self[span])
let tables = self.0.borrow();
tables.tcx.sess.source_map().span_to_diagnostic_string(tables[span])
}
fn get_filename(&self, span: &Span) -> Filename {
let tables = self.0.borrow();
opaque(
&self
&tables
.tcx
.sess
.source_map()
.span_to_filename(self[*span])
.span_to_filename(tables[*span])
.display(rustc_span::FileNameDisplayPreference::Local)
.to_string(),
)
}
fn get_lines(&self, span: &Span) -> LineInfo {
let lines = &self.tcx.sess.source_map().span_to_location_info(self[*span]);
let tables = self.0.borrow();
let lines = &tables.tcx.sess.source_map().span_to_location_info(tables[*span]);
LineInfo { start_line: lines.1, start_col: lines.2, end_line: lines.3, end_col: lines.4 }
}
fn def_kind(&mut self, def_id: stable_mir::DefId) -> stable_mir::DefKind {
self.tcx.def_kind(self[def_id]).stable(self)
fn def_kind(&self, def_id: stable_mir::DefId) -> stable_mir::DefKind {
let mut tables = self.0.borrow_mut();
tables.tcx.def_kind(tables[def_id]).stable(&mut *tables)
}
fn span_of_an_item(&mut self, def_id: stable_mir::DefId) -> Span {
self.tcx.def_span(self[def_id]).stable(self)
fn span_of_an_item(&self, def_id: stable_mir::DefId) -> Span {
let mut tables = self.0.borrow_mut();
tables.tcx.def_span(tables[def_id]).stable(&mut *tables)
}
fn all_local_items(&mut self) -> stable_mir::CrateItems {
self.tcx.mir_keys(()).iter().map(|item| self.crate_item(item.to_def_id())).collect()
fn all_local_items(&self) -> stable_mir::CrateItems {
let mut tables = self.0.borrow_mut();
tables.tcx.mir_keys(()).iter().map(|item| tables.crate_item(item.to_def_id())).collect()
}
fn entry_fn(&mut self) -> Option<stable_mir::CrateItem> {
Some(self.crate_item(self.tcx.entry_fn(())?.0))
fn entry_fn(&self) -> Option<stable_mir::CrateItem> {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
Some(tables.crate_item(tcx.entry_fn(())?.0))
}
fn all_trait_decls(&mut self) -> stable_mir::TraitDecls {
self.tcx
fn all_trait_decls(&self) -> stable_mir::TraitDecls {
let mut tables = self.0.borrow_mut();
tables
.tcx
.traits(LOCAL_CRATE)
.iter()
.map(|trait_def_id| self.trait_def(*trait_def_id))
.map(|trait_def_id| tables.trait_def(*trait_def_id))
.collect()
}
fn trait_decl(&mut self, trait_def: &stable_mir::ty::TraitDef) -> stable_mir::ty::TraitDecl {
let def_id = self[trait_def.0];
let trait_def = self.tcx.trait_def(def_id);
trait_def.stable(self)
fn trait_decl(&self, trait_def: &stable_mir::ty::TraitDef) -> stable_mir::ty::TraitDecl {
let mut tables = self.0.borrow_mut();
let def_id = tables[trait_def.0];
let trait_def = tables.tcx.trait_def(def_id);
trait_def.stable(&mut *tables)
}
fn all_trait_impls(&mut self) -> stable_mir::ImplTraitDecls {
self.tcx
fn all_trait_impls(&self) -> stable_mir::ImplTraitDecls {
let mut tables = self.0.borrow_mut();
tables
.tcx
.trait_impls_in_crate(LOCAL_CRATE)
.iter()
.map(|impl_def_id| self.impl_def(*impl_def_id))
.map(|impl_def_id| tables.impl_def(*impl_def_id))
.collect()
}
fn trait_impl(&mut self, impl_def: &stable_mir::ty::ImplDef) -> stable_mir::ty::ImplTrait {
let def_id = self[impl_def.0];
let impl_trait = self.tcx.impl_trait_ref(def_id).unwrap();
impl_trait.stable(self)
fn trait_impl(&self, impl_def: &stable_mir::ty::ImplDef) -> stable_mir::ty::ImplTrait {
let mut tables = self.0.borrow_mut();
let def_id = tables[impl_def.0];
let impl_trait = tables.tcx.impl_trait_ref(def_id).unwrap();
impl_trait.stable(&mut *tables)
}
fn mir_body(&mut self, item: stable_mir::DefId) -> stable_mir::mir::Body {
let def_id = self[item];
self.tcx.instance_mir(ty::InstanceDef::Item(def_id)).stable(self)
fn mir_body(&self, item: stable_mir::DefId) -> stable_mir::mir::Body {
let mut tables = self.0.borrow_mut();
let def_id = tables[item];
tables.tcx.instance_mir(ty::InstanceDef::Item(def_id)).stable(&mut tables)
}
fn ty_kind(&mut self, ty: stable_mir::ty::Ty) -> TyKind {
self.types[ty.0].clone().stable(self)
fn ty_kind(&self, ty: stable_mir::ty::Ty) -> TyKind {
let mut tables = self.0.borrow_mut();
tables.types[ty.0].clone().stable(&mut *tables)
}
fn mk_ty(&mut self, kind: TyKind) -> stable_mir::ty::Ty {
let n = self.types.len();
self.types.push(MaybeStable::Stable(kind));
fn mk_ty(&self, kind: TyKind) -> stable_mir::ty::Ty {
let mut tables = self.0.borrow_mut();
let n = tables.types.len();
tables.types.push(MaybeStable::Stable(kind));
stable_mir::ty::Ty(n)
}
fn generics_of(&mut self, def_id: stable_mir::DefId) -> stable_mir::ty::Generics {
let def_id = self[def_id];
let generics = self.tcx.generics_of(def_id);
generics.stable(self)
fn generics_of(&self, def_id: stable_mir::DefId) -> stable_mir::ty::Generics {
let mut tables = self.0.borrow_mut();
let def_id = tables[def_id];
let generics = tables.tcx.generics_of(def_id);
generics.stable(&mut *tables)
}
fn predicates_of(&mut self, def_id: stable_mir::DefId) -> stable_mir::ty::GenericPredicates {
let def_id = self[def_id];
let ty::GenericPredicates { parent, predicates } = self.tcx.predicates_of(def_id);
fn predicates_of(&self, def_id: stable_mir::DefId) -> stable_mir::ty::GenericPredicates {
let mut tables = self.0.borrow_mut();
let def_id = tables[def_id];
let ty::GenericPredicates { parent, predicates } = tables.tcx.predicates_of(def_id);
stable_mir::ty::GenericPredicates {
parent: parent.map(|did| self.trait_def(did)),
parent: parent.map(|did| tables.trait_def(did)),
predicates: predicates
.iter()
.map(|(clause, span)| {
(clause.as_predicate().kind().skip_binder().stable(self), span.stable(self))
(
clause.as_predicate().kind().skip_binder().stable(&mut *tables),
span.stable(&mut *tables),
)
})
.collect(),
}
}
fn explicit_predicates_of(
&mut self,
&self,
def_id: stable_mir::DefId,
) -> stable_mir::ty::GenericPredicates {
let def_id = self[def_id];
let ty::GenericPredicates { parent, predicates } = self.tcx.explicit_predicates_of(def_id);
let mut tables = self.0.borrow_mut();
let def_id = tables[def_id];
let ty::GenericPredicates { parent, predicates } =
tables.tcx.explicit_predicates_of(def_id);
stable_mir::ty::GenericPredicates {
parent: parent.map(|did| self.trait_def(did)),
parent: parent.map(|did| tables.trait_def(did)),
predicates: predicates
.iter()
.map(|(clause, span)| {
(clause.as_predicate().kind().skip_binder().stable(self), span.stable(self))
(
clause.as_predicate().kind().skip_binder().stable(&mut *tables),
span.stable(&mut *tables),
)
})
.collect(),
}
}
fn instance_body(&mut self, def: InstanceDef) -> Body {
let instance = self.instances[def];
builder::BodyBuilder::new(self.tcx, instance).build(self)
fn instance_body(&self, def: InstanceDef) -> Body {
let mut tables = self.0.borrow_mut();
let instance = tables.instances[def];
builder::BodyBuilder::new(tables.tcx, instance).build(&mut *tables)
}
fn instance_ty(&mut self, def: InstanceDef) -> stable_mir::ty::Ty {
let instance = self.instances[def];
let ty = instance.ty(self.tcx, ParamEnv::empty());
self.intern_ty(ty)
fn instance_ty(&self, def: InstanceDef) -> stable_mir::ty::Ty {
let mut tables = self.0.borrow_mut();
let instance = tables.instances[def];
let ty = instance.ty(tables.tcx, ParamEnv::empty());
tables.intern_ty(ty)
}
fn instance_def_id(&mut self, def: InstanceDef) -> stable_mir::DefId {
let def_id = self.instances[def].def_id();
self.create_def_id(def_id)
fn instance_def_id(&self, def: InstanceDef) -> stable_mir::DefId {
let mut tables = self.0.borrow_mut();
let def_id = tables.instances[def].def_id();
tables.create_def_id(def_id)
}
fn mono_instance(&mut self, item: stable_mir::CrateItem) -> stable_mir::mir::mono::Instance {
let def_id = self[item.0];
Instance::mono(self.tcx, def_id).stable(self)
fn mono_instance(&self, item: stable_mir::CrateItem) -> stable_mir::mir::mono::Instance {
let mut tables = self.0.borrow_mut();
let def_id = tables[item.0];
Instance::mono(tables.tcx, def_id).stable(&mut *tables)
}
fn requires_monomorphization(&self, def_id: stable_mir::DefId) -> bool {
let def_id = self[def_id];
let generics = self.tcx.generics_of(def_id);
let result = generics.requires_monomorphization(self.tcx);
let tables = self.0.borrow();
let def_id = tables[def_id];
let generics = tables.tcx.generics_of(def_id);
let result = generics.requires_monomorphization(tables.tcx);
result
}
fn resolve_instance(
&mut self,
&self,
def: stable_mir::ty::FnDef,
args: &stable_mir::ty::GenericArgs,
) -> Option<stable_mir::mir::mono::Instance> {
let def_id = def.0.internal(self);
let args_ref = args.internal(self);
match Instance::resolve(self.tcx, ParamEnv::reveal_all(), def_id, args_ref) {
Ok(Some(instance)) => Some(instance.stable(self)),
let mut tables = self.0.borrow_mut();
let def_id = def.0.internal(&mut *tables);
let args_ref = args.internal(&mut *tables);
match Instance::resolve(tables.tcx, ParamEnv::reveal_all(), def_id, args_ref) {
Ok(Some(instance)) => Some(instance.stable(&mut *tables)),
Ok(None) | Err(_) => None,
}
}
@ -241,13 +279,15 @@ impl<S, R: PartialEq> PartialEq<R> for MaybeStable<S, R> {
}
}
pub(crate) struct TablesWrapper<'tcx>(pub(crate) RefCell<Tables<'tcx>>);
pub struct Tables<'tcx> {
pub tcx: TyCtxt<'tcx>,
pub def_ids: IndexMap<DefId, stable_mir::DefId>,
pub alloc_ids: IndexMap<AllocId, stable_mir::AllocId>,
pub spans: IndexMap<rustc_span::Span, Span>,
pub types: Vec<MaybeStable<TyKind, Ty<'tcx>>>,
pub instances: IndexMap<ty::Instance<'tcx>, InstanceDef>,
pub(crate) tcx: TyCtxt<'tcx>,
pub(crate) def_ids: IndexMap<DefId, stable_mir::DefId>,
pub(crate) alloc_ids: IndexMap<AllocId, stable_mir::AllocId>,
pub(crate) spans: IndexMap<rustc_span::Span, Span>,
pub(crate) types: Vec<MaybeStable<TyKind, Ty<'tcx>>>,
pub(crate) instances: IndexMap<ty::Instance<'tcx>, InstanceDef>,
}
impl<'tcx> Tables<'tcx> {
@ -270,7 +310,7 @@ fn smir_crate(tcx: TyCtxt<'_>, crate_num: CrateNum) -> stable_mir::Crate {
}
/// Trait used to convert between an internal MIR type to a Stable MIR type.
pub(crate) trait Stable<'tcx> {
pub trait Stable<'tcx> {
/// The stable representation of the type implementing Stable.
type T;
/// Converts an object to the equivalent Stable MIR representation.

View File

@ -957,6 +957,7 @@ symbols! {
log_syntax,
logf32,
logf64,
loongarch_target_feature,
loop_break_value,
lt,
macro_at_most_once_rep,

View File

@ -175,17 +175,17 @@ pub fn trait_impl(trait_impl: &ImplDef) -> ImplTrait {
}
pub trait Context {
fn entry_fn(&mut self) -> Option<CrateItem>;
fn entry_fn(&self) -> Option<CrateItem>;
/// Retrieve all items of the local crate that have a MIR associated with them.
fn all_local_items(&mut self) -> CrateItems;
fn mir_body(&mut self, item: DefId) -> mir::Body;
fn all_trait_decls(&mut self) -> TraitDecls;
fn trait_decl(&mut self, trait_def: &TraitDef) -> TraitDecl;
fn all_trait_impls(&mut self) -> ImplTraitDecls;
fn trait_impl(&mut self, trait_impl: &ImplDef) -> ImplTrait;
fn generics_of(&mut self, def_id: DefId) -> Generics;
fn predicates_of(&mut self, def_id: DefId) -> GenericPredicates;
fn explicit_predicates_of(&mut self, def_id: DefId) -> GenericPredicates;
fn all_local_items(&self) -> CrateItems;
fn mir_body(&self, item: DefId) -> mir::Body;
fn all_trait_decls(&self) -> TraitDecls;
fn trait_decl(&self, trait_def: &TraitDef) -> TraitDecl;
fn all_trait_impls(&self) -> ImplTraitDecls;
fn trait_impl(&self, trait_impl: &ImplDef) -> ImplTrait;
fn generics_of(&self, def_id: DefId) -> Generics;
fn predicates_of(&self, def_id: DefId) -> GenericPredicates;
fn explicit_predicates_of(&self, def_id: DefId) -> GenericPredicates;
/// Get information about the local crate.
fn local_crate(&self) -> Crate;
/// Retrieve a list of all external crates.
@ -207,61 +207,58 @@ pub trait Context {
fn get_lines(&self, span: &Span) -> LineInfo;
/// Returns the `kind` of given `DefId`
fn def_kind(&mut self, def_id: DefId) -> DefKind;
fn def_kind(&self, def_id: DefId) -> DefKind;
/// `Span` of an item
fn span_of_an_item(&mut self, def_id: DefId) -> Span;
fn span_of_an_item(&self, def_id: DefId) -> Span;
/// Obtain the representation of a type.
fn ty_kind(&mut self, ty: Ty) -> TyKind;
fn ty_kind(&self, ty: Ty) -> TyKind;
/// Create a new `Ty` from scratch without information from rustc.
fn mk_ty(&mut self, kind: TyKind) -> Ty;
fn mk_ty(&self, kind: TyKind) -> Ty;
/// Get the body of an Instance.
/// FIXME: Monomorphize the body.
fn instance_body(&mut self, instance: InstanceDef) -> Body;
fn instance_body(&self, instance: InstanceDef) -> Body;
/// Get the instance type with generic substitutions applied and lifetimes erased.
fn instance_ty(&mut self, instance: InstanceDef) -> Ty;
fn instance_ty(&self, instance: InstanceDef) -> Ty;
/// Get the instance.
fn instance_def_id(&mut self, instance: InstanceDef) -> DefId;
fn instance_def_id(&self, instance: InstanceDef) -> DefId;
/// Convert a non-generic crate item into an instance.
/// This function will panic if the item is generic.
fn mono_instance(&mut self, item: CrateItem) -> Instance;
fn mono_instance(&self, item: CrateItem) -> Instance;
/// Item requires monomorphization.
fn requires_monomorphization(&self, def_id: DefId) -> bool;
/// Resolve an instance from the given function definition and generic arguments.
fn resolve_instance(&mut self, def: FnDef, args: &GenericArgs) -> Option<Instance>;
fn resolve_instance(&self, def: FnDef, args: &GenericArgs) -> Option<Instance>;
}
// A thread local variable that stores a pointer to the tables mapping between TyCtxt
// datastructures and stable MIR datastructures
scoped_thread_local! (static TLV: Cell<*mut ()>);
scoped_thread_local! (static TLV: Cell<*const ()>);
pub fn run(mut context: impl Context, f: impl FnOnce()) {
pub fn run(context: &dyn Context, f: impl FnOnce()) {
assert!(!TLV.is_set());
fn g<'a>(mut context: &mut (dyn Context + 'a), f: impl FnOnce()) {
let ptr: *mut () = &mut context as *mut &mut _ as _;
TLV.set(&Cell::new(ptr), || {
f();
});
}
g(&mut context, f);
let ptr: *const () = &context as *const &_ as _;
TLV.set(&Cell::new(ptr), || {
f();
});
}
/// Loads the current context and calls a function with it.
/// Do not nest these, as that will ICE.
pub fn with<R>(f: impl FnOnce(&mut dyn Context) -> R) -> R {
pub fn with<R>(f: impl FnOnce(&dyn Context) -> R) -> R {
assert!(TLV.is_set());
TLV.with(|tlv| {
let ptr = tlv.get();
assert!(!ptr.is_null());
f(unsafe { *(ptr as *mut &mut dyn Context) })
f(unsafe { *(ptr as *const &dyn Context) })
})
}

View File

@ -1,6 +1,4 @@
use crate::cmp::Ordering;
use crate::fmt::{self, Write};
use crate::hash;
use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use super::display_buffer::DisplayBuffer;
@ -63,7 +61,7 @@ pub enum SocketAddr {
/// assert_eq!(socket.ip(), &Ipv4Addr::new(127, 0, 0, 1));
/// assert_eq!(socket.port(), 8080);
/// ```
#[derive(Copy, Clone, Eq, PartialEq)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct SocketAddrV4 {
ip: Ipv4Addr,
@ -96,7 +94,7 @@ pub struct SocketAddrV4 {
/// assert_eq!(socket.ip(), &Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1));
/// assert_eq!(socket.port(), 8080);
/// ```
#[derive(Copy, Clone, Eq, PartialEq)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct SocketAddrV6 {
ip: Ipv6Addr,
@ -644,48 +642,3 @@ impl fmt::Debug for SocketAddrV6 {
fmt::Display::fmt(self, fmt)
}
}
#[stable(feature = "socketaddr_ordering", since = "1.45.0")]
impl PartialOrd for SocketAddrV4 {
#[inline]
fn partial_cmp(&self, other: &SocketAddrV4) -> Option<Ordering> {
Some(self.cmp(other))
}
}
#[stable(feature = "socketaddr_ordering", since = "1.45.0")]
impl PartialOrd for SocketAddrV6 {
#[inline]
fn partial_cmp(&self, other: &SocketAddrV6) -> Option<Ordering> {
Some(self.cmp(other))
}
}
#[stable(feature = "socketaddr_ordering", since = "1.45.0")]
impl Ord for SocketAddrV4 {
#[inline]
fn cmp(&self, other: &SocketAddrV4) -> Ordering {
self.ip().cmp(other.ip()).then(self.port().cmp(&other.port()))
}
}
#[stable(feature = "socketaddr_ordering", since = "1.45.0")]
impl Ord for SocketAddrV6 {
#[inline]
fn cmp(&self, other: &SocketAddrV6) -> Ordering {
self.ip().cmp(other.ip()).then(self.port().cmp(&other.port()))
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl hash::Hash for SocketAddrV4 {
fn hash<H: hash::Hasher>(&self, s: &mut H) {
(self.port, self.ip).hash(s)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl hash::Hash for SocketAddrV6 {
fn hash<H: hash::Hasher>(&self, s: &mut H) {
(self.port, &self.ip, self.flowinfo, self.scope_id).hash(s)
}
}

View File

@ -199,6 +199,9 @@ fn compare() {
let v6_1 = "[2001:db8:f00::1002]:23456".parse::<SocketAddrV6>().unwrap();
let v6_2 = "[2001:db8:f00::2001]:12345".parse::<SocketAddrV6>().unwrap();
let v6_3 = "[2001:db8:f00::2001]:23456".parse::<SocketAddrV6>().unwrap();
let v6_4 = "[2001:db8:f00::2001%42]:23456".parse::<SocketAddrV6>().unwrap();
let mut v6_5 = "[2001:db8:f00::2001]:23456".parse::<SocketAddrV6>().unwrap();
v6_5.set_flowinfo(17);
// equality
assert_eq!(v4_1, v4_1);
@ -207,6 +210,8 @@ fn compare() {
assert_eq!(SocketAddr::V6(v6_1), SocketAddr::V6(v6_1));
assert!(v4_1 != v4_2);
assert!(v6_1 != v6_2);
assert!(v6_3 != v6_4);
assert!(v6_3 != v6_5);
// compare different addresses
assert!(v4_1 < v4_2);
@ -226,6 +231,12 @@ fn compare() {
assert!(v4_3 > v4_1);
assert!(v6_3 > v6_1);
// compare the same address with different scope_id
assert!(v6_3 < v6_4);
// compare the same address with different flowinfo
assert!(v6_3 < v6_5);
// compare with an inferred right-hand side
assert_eq!(v4_1, "224.120.45.1:23456".parse().unwrap());
assert_eq!(v6_1, "[2001:db8:f00::1002]:23456".parse().unwrap());

View File

@ -1,5 +1,5 @@
// run-pass
// Test that users are able to use stable mir APIs to retrieve monomorphized instances
//! Test that users are able to use stable mir APIs to retrieve monomorphized instances
// ignore-stage1
// ignore-cross-compile
@ -14,15 +14,15 @@
extern crate rustc_middle;
#[macro_use]
extern crate rustc_smir;
extern crate stable_mir;
extern crate rustc_driver;
extern crate rustc_interface;
extern crate stable_mir;
use rustc_middle::ty::TyCtxt;
use mir::{mono::Instance, TerminatorKind::*};
use stable_mir::ty::{TyKind, RigidTy};
use stable_mir::*;
use rustc_middle::ty::TyCtxt;
use rustc_smir::rustc_internal;
use stable_mir::ty::{RigidTy, TyKind};
use stable_mir::*;
use std::io::Write;
use std::ops::ControlFlow;
@ -33,16 +33,16 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
let items = stable_mir::all_local_items();
// Get all items and split generic vs monomorphic items.
let (generic, mono) : (Vec<_>, Vec<_>) = items.into_iter().partition(|item| {
item.requires_monomorphization()
});
let (generic, mono): (Vec<_>, Vec<_>) =
items.into_iter().partition(|item| item.requires_monomorphization());
assert_eq!(mono.len(), 3, "Expected 2 mono functions and one constant");
assert_eq!(generic.len(), 2, "Expected 2 generic functions");
// For all monomorphic items, get the correspondent instances.
let instances = mono.iter().filter_map(|item| {
mir::mono::Instance::try_from(*item).ok()
}).collect::<Vec<mir::mono::Instance>>();
let instances = mono
.iter()
.filter_map(|item| mir::mono::Instance::try_from(*item).ok())
.collect::<Vec<mir::mono::Instance>>();
assert_eq!(instances.len(), mono.len());
// For all generic items, try_from should fail.
@ -58,19 +58,22 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
fn test_body(body: mir::Body) {
for term in body.blocks.iter().map(|bb| &bb.terminator) {
match &term.kind {
Call{ func, .. } => {
Call { func, .. } => {
let TyKind::RigidTy(ty) = func.ty(&body.locals).kind() else { unreachable!() };
let RigidTy::FnDef(def, args) = ty else { unreachable!() };
let result = Instance::resolve(def, &args);
assert!(result.is_ok());
}
Goto {..} | Assert{..} | SwitchInt{..} | Return | Drop {..} => { /* Do nothing */}
_ => { unreachable!("Unexpected terminator {term:?}") }
Goto { .. } | Assert { .. } | SwitchInt { .. } | Return | Drop { .. } => {
/* Do nothing */
}
_ => {
unreachable!("Unexpected terminator {term:?}")
}
}
}
}
/// This test will generate and analyze a dummy crate using the stable mir.
/// For that, it will first write the dummy crate into a file.
/// Then it will create a `StableMir` using custom arguments and then

View File

@ -0,0 +1,64 @@
// run-pass
//! Test that users are able to use retrieve internal constructs from stable ones to help with
//! the migration.
// ignore-stage1
// ignore-cross-compile
// ignore-remote
// ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837
// edition: 2021
#![feature(rustc_private)]
#![feature(assert_matches)]
#![feature(control_flow_enum)]
#[macro_use]
extern crate rustc_smir;
extern crate rustc_driver;
extern crate rustc_interface;
extern crate rustc_middle;
extern crate stable_mir;
use rustc_middle::ty::TyCtxt;
use rustc_smir::rustc_internal;
use std::io::Write;
use std::ops::ControlFlow;
const CRATE_NAME: &str = "input";
fn test_translation(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
let main_fn = stable_mir::entry_fn().unwrap();
let body = main_fn.body();
let orig_ty = body.locals[0].ty;
let rustc_ty = rustc_internal::internal(&orig_ty);
assert!(rustc_ty.is_unit());
ControlFlow::Continue(())
}
/// This test will generate and analyze a dummy crate using the stable mir.
/// For that, it will first write the dummy crate into a file.
/// Then it will create a `StableMir` using custom arguments and then
/// it will run the compiler.
fn main() {
let path = "internal_input.rs";
generate_input(&path).unwrap();
let args = vec![
"rustc".to_string(),
"--crate-name".to_string(),
CRATE_NAME.to_string(),
path.to_string(),
];
run!(args, tcx, test_translation(tcx)).unwrap();
}
fn generate_input(path: &str) -> std::io::Result<()> {
let mut file = std::fs::File::create(path)?;
write!(
file,
r#"
pub fn main() {{
}}
"#
)?;
Ok(())
}

View File

@ -30,6 +30,7 @@
// revisions: loongarch64
//[loongarch64] compile-flags: --target loongarch64-unknown-linux-gnu
//[loongarch64] needs-llvm-components: loongarch
//[loongarch64] min-llvm-version: 17
// revisions: wasm
//[wasm] compile-flags: --target wasm32-unknown-unknown
//[wasm] needs-llvm-components: webassembly

View File

@ -1,7 +1,5 @@
// edition: 2021
#![allow(incomplete_features)]
use std::future::Future;
use std::pin::Pin;

View File

@ -1,11 +1,11 @@
error[E0053]: method `foo` has an incompatible type for trait
--> $DIR/async-example-desugared-boxed-in-trait.rs:13:5
--> $DIR/async-example-desugared-boxed-in-trait.rs:11:5
|
LL | async fn foo(&self) -> i32 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Pin<Box<dyn Future<Output = i32>>>`, found future
|
note: type in trait
--> $DIR/async-example-desugared-boxed-in-trait.rs:9:22
--> $DIR/async-example-desugared-boxed-in-trait.rs:7:22
|
LL | fn foo(&self) -> Pin<Box<dyn Future<Output = i32> + '_>>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -1,7 +1,5 @@
// edition: 2021
#![allow(incomplete_features)]
use std::future::Future;
use std::pin::Pin;

View File

@ -1,5 +1,5 @@
error: method `foo` should be async because the method from the trait is async
--> $DIR/async-example-desugared-boxed.rs:13:5
--> $DIR/async-example-desugared-boxed.rs:11:5
|
LL | async fn foo(&self) -> i32;
| --------------------------- required because the trait method is async

View File

@ -2,7 +2,6 @@
// edition: 2021
#![feature(lint_reasons)]
#![allow(incomplete_features)]
use std::future::Future;
use std::pin::Pin;

View File

@ -1,8 +1,6 @@
// check-pass
// edition: 2021
#![allow(incomplete_features)]
use std::future::Future;
trait MyTrait {

View File

@ -1,7 +1,5 @@
// edition: 2021
#![allow(incomplete_features)]
use std::future::Future;
use std::task::Poll;

View File

@ -1,5 +1,5 @@
error: method `foo` should be async because the method from the trait is async
--> $DIR/async-example-desugared-manual.rs:21:5
--> $DIR/async-example-desugared-manual.rs:19:5
|
LL | async fn foo(&self) -> i32;
| --------------------------- required because the trait method is async

View File

@ -1,8 +1,6 @@
// check-pass
// edition: 2021
#![allow(incomplete_features)]
use std::future::Future;
trait MyTrait {

View File

@ -1,8 +1,6 @@
// check-pass
// edition: 2021
#![allow(incomplete_features)]
trait MyTrait {
#[allow(async_fn_in_trait)]
async fn foo(&self) -> i32;

View File

@ -2,8 +2,6 @@
// known-bug: #102682
// edition: 2021
#![allow(incomplete_features)]
use std::fmt::Debug;
use std::hash::Hash;

View File

@ -1,5 +1,5 @@
error[E0311]: the parameter type `U` may not live long enough
--> $DIR/async-generics-and-bounds.rs:11:5
--> $DIR/async-generics-and-bounds.rs:9:5
|
LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
| ^^^^^^^^^^^^^-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -13,7 +13,7 @@ LL | async fn foo<'a>(&'a self) -> &'a (T, U) where T: Debug + Sized, U: Has
| ++++ ++ ++ +++++++
error[E0311]: the parameter type `T` may not live long enough
--> $DIR/async-generics-and-bounds.rs:11:5
--> $DIR/async-generics-and-bounds.rs:9:5
|
LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
| ^^^^^^^^^^^^^-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -2,8 +2,6 @@
// known-bug: #102682
// edition: 2021
#![allow(incomplete_features)]
trait MyTrait<T, U> {
async fn foo(&self) -> &(T, U);
}

View File

@ -1,5 +1,5 @@
error[E0311]: the parameter type `U` may not live long enough
--> $DIR/async-generics.rs:8:5
--> $DIR/async-generics.rs:6:5
|
LL | async fn foo(&self) -> &(T, U);
| ^^^^^^^^^^^^^-^^^^^^^^^^^^^^^^^
@ -13,7 +13,7 @@ LL | async fn foo<'a>(&'a self) -> &'a (T, U) where U: 'a;
| ++++ ++ ++ +++++++++++
error[E0311]: the parameter type `T` may not live long enough
--> $DIR/async-generics.rs:8:5
--> $DIR/async-generics.rs:6:5
|
LL | async fn foo(&self) -> &(T, U);
| ^^^^^^^^^^^^^-^^^^^^^^^^^^^^^^^

View File

@ -1,8 +1,6 @@
// check-pass
// edition: 2021
#![allow(incomplete_features)]
use std::fmt::Debug;
trait MyTrait<'a, 'b, T> {

View File

@ -1,8 +1,6 @@
// check-pass
// edition: 2021
#![allow(incomplete_features)]
trait MyTrait<'a, 'b, T> {
#[allow(async_fn_in_trait)]
async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T);

View File

@ -1,7 +1,5 @@
// edition: 2021
#![allow(incomplete_features)]
trait MyTrait<T> {
async fn foo_recursive(&self, n: usize) -> T;
}

View File

@ -1,5 +1,5 @@
error[E0733]: recursion in an `async fn` requires boxing
--> $DIR/async-recursive-generic.rs:10:5
--> $DIR/async-recursive-generic.rs:8:5
|
LL | async fn foo_recursive(&self, n: usize) -> T {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ recursive `async fn`

View File

@ -1,7 +1,5 @@
// edition: 2021
#![allow(incomplete_features)]
trait MyTrait {
async fn foo_recursive(&self, n: usize) -> i32;
}

View File

@ -1,5 +1,5 @@
error[E0733]: recursion in an `async fn` requires boxing
--> $DIR/async-recursive.rs:10:5
--> $DIR/async-recursive.rs:8:5
|
LL | async fn foo_recursive(&self, n: usize) -> i32 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ recursive `async fn`

View File

@ -1,8 +1,6 @@
// check-pass
// edition:2021
#![allow(incomplete_features)]
pub trait Foo {
#[allow(async_fn_in_trait)]
async fn foo(&mut self);

View File

@ -1,5 +1,3 @@
#![allow(incomplete_features)]
struct Wrapper<T>(T);
trait Foo {

View File

@ -1,5 +1,5 @@
error[E0053]: method `bar` has an incompatible return type for trait
--> $DIR/deep-match.rs:10:17
--> $DIR/deep-match.rs:8:17
|
LL | fn bar() -> i32 {
| ^^^

View File

@ -1,5 +1,3 @@
#![allow(incomplete_features)]
use std::ops::Deref;
pub trait Foo {

View File

@ -1,5 +1,5 @@
error[E0271]: type mismatch resolving `<&i32 as Deref>::Target == String`
--> $DIR/default-body-type-err.rs:6:22
--> $DIR/default-body-type-err.rs:4:22
|
LL | fn lol(&self) -> impl Deref<Target = String> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `String`

View File

@ -1,5 +1,3 @@
#![allow(incomplete_features)]
trait Foo {
fn bar() -> impl std::fmt::Display;
}

View File

@ -1,5 +1,5 @@
error[E0277]: `()` doesn't implement `std::fmt::Display`
--> $DIR/doesnt-satisfy.rs:8:17
--> $DIR/doesnt-satisfy.rs:6:17
|
LL | fn bar() -> () {}
| ^^ `()` cannot be formatted with the default formatter
@ -7,7 +7,7 @@ LL | fn bar() -> () {}
= help: the trait `std::fmt::Display` is not implemented for `()`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
note: required by a bound in `Foo::{opaque#0}`
--> $DIR/doesnt-satisfy.rs:4:22
--> $DIR/doesnt-satisfy.rs:2:22
|
LL | fn bar() -> impl std::fmt::Display;
| ^^^^^^^^^^^^^^^^^ required by this bound in `Foo::{opaque#0}`

View File

@ -1,5 +1,3 @@
#![allow(incomplete_features)]
struct U;
trait Foo {

View File

@ -1,5 +1,5 @@
error[E0049]: method `bar` has 1 type parameter but its trait declaration has 0 type parameters
--> $DIR/generics-mismatch.rs:10:12
--> $DIR/generics-mismatch.rs:8:12
|
LL | fn bar(&self) -> impl Sized;
| - expected 0 type parameters

View File

@ -1,5 +1,3 @@
#![allow(incomplete_features)]
trait Marker {}
impl Marker for u32 {}

View File

@ -1,5 +1,5 @@
error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied
--> $DIR/issue-102140.rs:22:22
--> $DIR/issue-102140.rs:20:22
|
LL | MyTrait::foo(&self)
| ------------ ^^^^^ the trait `MyTrait` is not implemented for `&dyn MyTrait`
@ -13,7 +13,7 @@ LL + MyTrait::foo(self)
|
error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied
--> $DIR/issue-102140.rs:22:9
--> $DIR/issue-102140.rs:20:9
|
LL | MyTrait::foo(&self)
| ^^^^^^^^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `&dyn MyTrait`
@ -21,7 +21,7 @@ LL | MyTrait::foo(&self)
= help: the trait `MyTrait` is implemented for `Outer`
error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied
--> $DIR/issue-102140.rs:22:9
--> $DIR/issue-102140.rs:20:9
|
LL | MyTrait::foo(&self)
| ^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `&dyn MyTrait`

View File

@ -1,5 +1,3 @@
#![allow(incomplete_features)]
use std::fmt::Display;
use std::ops::Deref;

View File

@ -1,5 +1,5 @@
error[E0308]: mismatched types
--> $DIR/issue-102571.rs:11:9
--> $DIR/issue-102571.rs:9:9
|
LL | let () = t.bar();
| ^^ ------- this expression has type `impl Deref<Target = impl std::fmt::Display + ?Sized>`

View File

@ -1,5 +1,3 @@
#![allow(incomplete_features)]
use std::fmt::Debug;
trait Foo {

View File

@ -1,11 +1,11 @@
error[E0038]: the trait `Foo` cannot be made into an object
--> $DIR/object-safety.rs:16:33
--> $DIR/object-safety.rs:14:33
|
LL | let i = Box::new(42_u32) as Box<dyn Foo>;
| ^^^^^^^^^^^^ `Foo` cannot be made into an object
|
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/object-safety.rs:6:22
--> $DIR/object-safety.rs:4:22
|
LL | trait Foo {
| --- this trait cannot be made into an object...
@ -14,13 +14,13 @@ LL | fn baz(&self) -> impl Debug;
= help: consider moving `baz` to another trait
error[E0038]: the trait `Foo` cannot be made into an object
--> $DIR/object-safety.rs:19:15
--> $DIR/object-safety.rs:17:15
|
LL | let s = i.baz();
| ^^^ `Foo` cannot be made into an object
|
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/object-safety.rs:6:22
--> $DIR/object-safety.rs:4:22
|
LL | trait Foo {
| --- this trait cannot be made into an object...
@ -29,13 +29,13 @@ LL | fn baz(&self) -> impl Debug;
= help: consider moving `baz` to another trait
error[E0038]: the trait `Foo` cannot be made into an object
--> $DIR/object-safety.rs:19:13
--> $DIR/object-safety.rs:17:13
|
LL | let s = i.baz();
| ^^^^^^^ `Foo` cannot be made into an object
|
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/object-safety.rs:6:22
--> $DIR/object-safety.rs:4:22
|
LL | trait Foo {
| --- this trait cannot be made into an object...
@ -44,13 +44,13 @@ LL | fn baz(&self) -> impl Debug;
= help: consider moving `baz` to another trait
error[E0038]: the trait `Foo` cannot be made into an object
--> $DIR/object-safety.rs:16:13
--> $DIR/object-safety.rs:14:13
|
LL | let i = Box::new(42_u32) as Box<dyn Foo>;
| ^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object
|
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/object-safety.rs:6:22
--> $DIR/object-safety.rs:4:22
|
LL | trait Foo {
| --- this trait cannot be made into an object...

View File

@ -1,5 +1,3 @@
#![allow(incomplete_features)]
use std::fmt::Display;
trait Foo {

View File

@ -1,5 +1,5 @@
error[E0308]: mismatched types
--> $DIR/opaque-in-impl-is-opaque.rs:16:19
--> $DIR/opaque-in-impl-is-opaque.rs:14:19
|
LL | fn bar(&self) -> impl Display {
| ------------ the found opaque type

View File

@ -1,5 +1,3 @@
#![allow(incomplete_features)]
struct S;
trait Foo {

View File

@ -1,5 +1,5 @@
error[E0049]: method `bar` has 0 type parameters but its trait declaration has 1 type parameter
--> $DIR/trait-more-generics-than-impl.rs:10:11
--> $DIR/trait-more-generics-than-impl.rs:8:11
|
LL | fn bar<T>() -> impl Sized;
| - expected 1 type parameter

View File

@ -1,2 +1,2 @@
error: incorrect value `bad-value` for codegen option `instrument-coverage` - `all` (default), `except-unused-generics`, `except-unused-functions`, or `off` was expected
error: incorrect value `bad-value` for codegen option `instrument-coverage` - `all` (default), `branch`, `except-unused-generics`, `except-unused-functions`, or `off` was expected

View File

@ -1,2 +1,2 @@
error: incorrect value `` for codegen option `instrument-coverage` - `all` (default), `except-unused-generics`, `except-unused-functions`, or `off` was expected
error: incorrect value `` for codegen option `instrument-coverage` - `all` (default), `branch`, `except-unused-generics`, `except-unused-functions`, or `off` was expected

View File

@ -1,2 +1,2 @@
error: `-C instrument-coverage=except-*` requires `-Z unstable-options`
error: `-C instrument-coverage=branch` and `-C instrument-coverage=except-*` require `-Z unstable-options`

View File

@ -1,2 +1,2 @@
error: `-C instrument-coverage=except-*` requires `-Z unstable-options`
error: `-C instrument-coverage=branch` and `-C instrument-coverage=except-*` require `-Z unstable-options`

View File

@ -44,6 +44,10 @@ LL | fn parse_type(iter: Box<dyn Iterator<Item=&str>+'static>) -> &str { iter.ne
|
= note: expected reference `&str`
found enum `Option<&str>`
help: consider using `Option::expect` to unwrap the `Option<&str>` value, panicking if the value is an `Option::None`
|
LL | fn parse_type(iter: Box<dyn Iterator<Item=&str>+'static>) -> &str { iter.next().expect("REASON") }
| +++++++++++++++++
error[E0061]: this function takes 1 argument but 0 arguments were supplied
--> $DIR/issue-26638.rs:5:47

View File

@ -0,0 +1,23 @@
#![allow(unused, dead_code)]
fn test_unwrap() -> Option<i32> {
let b: Result<i32, ()> = Ok(1);
let v: i32 = b; // return type is not `Result`, we don't suggest ? here
//~^ ERROR mismatched types
Some(v)
}
fn test_unwrap_option() -> Result<i32, ()> {
let b = Some(1);
let v: i32 = b; // return type is not `Option`, we don't suggest ? here
//~^ ERROR mismatched types
Ok(v)
}
fn main() {
let v: i32 = Some(0); //~ ERROR mismatched types
let c = Ok(false);
let v: i32 = c; //~ ERROR mismatched types
}

View File

@ -0,0 +1,55 @@
error[E0308]: mismatched types
--> $DIR/mismatch-ty-dont-suggest.rs:5:18
|
LL | let v: i32 = b; // return type is not `Result`, we don't suggest ? here
| --- ^ expected `i32`, found `Result<i32, ()>`
| |
| expected due to this
|
= note: expected type `i32`
found enum `Result<i32, ()>`
help: consider using `Result::expect` to unwrap the `Result<i32, ()>` value, panicking if the value is a `Result::Err`
|
LL | let v: i32 = b.expect("REASON"); // return type is not `Result`, we don't suggest ? here
| +++++++++++++++++
error[E0308]: mismatched types
--> $DIR/mismatch-ty-dont-suggest.rs:12:18
|
LL | let v: i32 = b; // return type is not `Option`, we don't suggest ? here
| --- ^ expected `i32`, found `Option<{integer}>`
| |
| expected due to this
|
= note: expected type `i32`
found enum `Option<{integer}>`
help: consider using `Option::expect` to unwrap the `Option<{integer}>` value, panicking if the value is an `Option::None`
|
LL | let v: i32 = b.expect("REASON"); // return type is not `Option`, we don't suggest ? here
| +++++++++++++++++
error[E0308]: mismatched types
--> $DIR/mismatch-ty-dont-suggest.rs:18:18
|
LL | let v: i32 = Some(0);
| --- ^^^^^^^ expected `i32`, found `Option<{integer}>`
| |
| expected due to this
|
= note: expected type `i32`
found enum `Option<{integer}>`
error[E0308]: mismatched types
--> $DIR/mismatch-ty-dont-suggest.rs:21:18
|
LL | let v: i32 = c;
| --- ^ expected `i32`, found `Result<bool, _>`
| |
| expected due to this
|
= note: expected type `i32`
found enum `Result<bool, _>`
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0308`.

View File

@ -0,0 +1,31 @@
// run-rustfix
#![allow(unused, dead_code)]
fn func() -> Option<i32> {
Some(1)
}
fn test_unwrap() -> Result<i32, ()> {
let b: Result<i32, ()> = Ok(1);
let v: i32 = b?; //~ ERROR mismatched types
Ok(v)
}
fn test_unwrap_option() -> Option<i32> {
let b = Some(1);
let v: i32 = b?; //~ ERROR mismatched types
Some(v)
}
fn main() {
let a = Some(1);
let v: i32 = a.expect("REASON"); //~ ERROR mismatched types
let b: Result<i32, ()> = Ok(1);
let v: i32 = b.expect("REASON"); //~ ERROR mismatched types
let v: i32 = func().expect("REASON"); //~ ERROR mismatched types
let a = None;
let v: i32 = a.expect("REASON"); //~ ERROR mismatched types
}

View File

@ -0,0 +1,31 @@
// run-rustfix
#![allow(unused, dead_code)]
fn func() -> Option<i32> {
Some(1)
}
fn test_unwrap() -> Result<i32, ()> {
let b: Result<i32, ()> = Ok(1);
let v: i32 = b; //~ ERROR mismatched types
Ok(v)
}
fn test_unwrap_option() -> Option<i32> {
let b = Some(1);
let v: i32 = b; //~ ERROR mismatched types
Some(v)
}
fn main() {
let a = Some(1);
let v: i32 = a; //~ ERROR mismatched types
let b: Result<i32, ()> = Ok(1);
let v: i32 = b; //~ ERROR mismatched types
let v: i32 = func(); //~ ERROR mismatched types
let a = None;
let v: i32 = a; //~ ERROR mismatched types
}

View File

@ -0,0 +1,93 @@
error[E0308]: mismatched types
--> $DIR/mismatch-ty-unwrap-expect.rs:10:18
|
LL | let v: i32 = b;
| --- ^ expected `i32`, found `Result<i32, ()>`
| |
| expected due to this
|
= note: expected type `i32`
found enum `Result<i32, ()>`
help: use the `?` operator to extract the `Result<i32, ()>` value, propagating a `Result::Err` value to the caller
|
LL | let v: i32 = b?;
| +
error[E0308]: mismatched types
--> $DIR/mismatch-ty-unwrap-expect.rs:16:18
|
LL | let v: i32 = b;
| --- ^ expected `i32`, found `Option<{integer}>`
| |
| expected due to this
|
= note: expected type `i32`
found enum `Option<{integer}>`
help: use the `?` operator to extract the `Option<{integer}>` value, propagating an `Option::None` value to the caller
|
LL | let v: i32 = b?;
| +
error[E0308]: mismatched types
--> $DIR/mismatch-ty-unwrap-expect.rs:22:18
|
LL | let v: i32 = a;
| --- ^ expected `i32`, found `Option<{integer}>`
| |
| expected due to this
|
= note: expected type `i32`
found enum `Option<{integer}>`
help: consider using `Option::expect` to unwrap the `Option<{integer}>` value, panicking if the value is an `Option::None`
|
LL | let v: i32 = a.expect("REASON");
| +++++++++++++++++
error[E0308]: mismatched types
--> $DIR/mismatch-ty-unwrap-expect.rs:25:18
|
LL | let v: i32 = b;
| --- ^ expected `i32`, found `Result<i32, ()>`
| |
| expected due to this
|
= note: expected type `i32`
found enum `Result<i32, ()>`
help: consider using `Result::expect` to unwrap the `Result<i32, ()>` value, panicking if the value is a `Result::Err`
|
LL | let v: i32 = b.expect("REASON");
| +++++++++++++++++
error[E0308]: mismatched types
--> $DIR/mismatch-ty-unwrap-expect.rs:27:18
|
LL | let v: i32 = func();
| --- ^^^^^^ expected `i32`, found `Option<i32>`
| |
| expected due to this
|
= note: expected type `i32`
found enum `Option<i32>`
help: consider using `Option::expect` to unwrap the `Option<i32>` value, panicking if the value is an `Option::None`
|
LL | let v: i32 = func().expect("REASON");
| +++++++++++++++++
error[E0308]: mismatched types
--> $DIR/mismatch-ty-unwrap-expect.rs:30:18
|
LL | let v: i32 = a;
| --- ^ expected `i32`, found `Option<_>`
| |
| expected due to this
|
= note: expected type `i32`
found enum `Option<_>`
help: consider using `Option::expect` to unwrap the `Option<_>` value, panicking if the value is an `Option::None`
|
LL | let v: i32 = a.expect("REASON");
| +++++++++++++++++
error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0308`.

View File

@ -8,6 +8,10 @@ LL | let x: isize = noexporttypelib::foo();
|
= note: expected type `isize`
found enum `Option<isize>`
help: consider using `Option::expect` to unwrap the `Option<isize>` value, panicking if the value is an `Option::None`
|
LL | let x: isize = noexporttypelib::foo().expect("REASON");
| +++++++++++++++++
error: aborting due to previous error

View File

@ -18,6 +18,7 @@
// gate-test-bpf_target_feature
// gate-test-aarch64_ver_target_feature
// gate-test-csky_target_feature
// gate-test-loongarch_target_feature
#[target_feature(enable = "avx512bw")]
//~^ ERROR: currently unstable

View File

@ -1,5 +1,5 @@
error[E0658]: the target feature `avx512bw` is currently unstable
--> $DIR/gate.rs:22:18
--> $DIR/gate.rs:23:18
|
LL | #[target_feature(enable = "avx512bw")]
| ^^^^^^^^^^^^^^^^^^^

View File

@ -8,6 +8,10 @@ LL | let x : char = last(y);
|
= note: expected type `char`
found enum `Option<_>`
help: consider using `Option::expect` to unwrap the `Option<_>` value, panicking if the value is an `Option::None`
|
LL | let x : char = last(y).expect("REASON");
| +++++++++++++++++
error: aborting due to previous error