diff options
Diffstat (limited to 'compiler/rustc_hir_analysis')
37 files changed, 1544 insertions, 926 deletions
diff --git a/compiler/rustc_hir_analysis/locales/en-US.ftl b/compiler/rustc_hir_analysis/messages.ftl index 1d313945b..1d7965ff5 100644 --- a/compiler/rustc_hir_analysis/locales/en-US.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -42,6 +42,9 @@ hir_analysis_assoc_type_binding_not_allowed = associated type bindings are not allowed here .label = associated type not allowed here +hir_analysis_parenthesized_fn_trait_expansion = + parenthesized trait syntax expands to `{$expanded_type}` + hir_analysis_typeof_reserved_keyword_used = `typeof` is a reserved keyword but unimplemented .suggestion = consider replacing `typeof(...)` with an actual type @@ -89,14 +92,14 @@ hir_analysis_missing_type_params = .note = because of the default `Self` reference, type parameters must be specified on object types hir_analysis_copy_impl_on_type_with_dtor = - the trait `Copy` may not be implemented for this type; the type has a destructor + the trait `Copy` cannot be implemented for this type; the type has a destructor .label = `Copy` not allowed on types with destructors hir_analysis_multiple_relaxed_default_bounds = type parameter has more than one relaxed default bound, only one is supported hir_analysis_copy_impl_on_non_adt = - the trait `Copy` may not be implemented for this type + the trait `Copy` cannot be implemented for this type .label = type is not a structure or enumeration hir_analysis_const_impl_for_non_const_trait = @@ -125,9 +128,14 @@ hir_analysis_where_clause_on_main = `main` function is not allowed to have a `wh hir_analysis_track_caller_on_main = `main` function is not allowed to be `#[track_caller]` .suggestion = remove this annotation +hir_analysis_target_feature_on_main = `main` function is not allowed to have `#[target_feature]` + hir_analysis_start_not_track_caller = `start` is not allowed to be `#[track_caller]` .label = `start` is not allowed to be `#[track_caller]` +hir_analysis_start_not_target_feature = `start` is not allowed to have `#[target_feature]` + .label = `start` is not allowed to have `#[target_feature]` + hir_analysis_start_not_async = `start` is not allowed to be `async` .label = `start` is not allowed to be `async` @@ -155,3 +163,65 @@ hir_analysis_cannot_capture_late_bound_ty_in_anon_const = hir_analysis_cannot_capture_late_bound_const_in_anon_const = cannot capture late-bound const parameter in a constant .label = parameter defined here + +hir_analysis_variances_of = {$variances_of} + +hir_analysis_pass_to_variadic_function = can't pass `{$ty}` to variadic function + .suggestion = cast the value to `{$cast_ty}` + .help = cast the value to `{$cast_ty}` + +hir_analysis_cast_thin_pointer_to_fat_pointer = cannot cast thin pointer `{$expr_ty}` to fat pointer `{$cast_ty}` + +hir_analysis_invalid_union_field = + field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union + .note = union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>` + +hir_analysis_invalid_union_field_sugg = + wrap the field type in `ManuallyDrop<...>` + +hir_analysis_return_type_notation_on_non_rpitit = + return type notation used on function that is not `async` and does not return `impl Trait` + .note = function returns `{$ty}`, which is not compatible with associated type return bounds + .label = this function must be `async` or return `impl Trait` + +hir_analysis_return_type_notation_equality_bound = + return type notation is not allowed to use type equality + +hir_analysis_return_type_notation_missing_method = + cannot find associated function `{$assoc_name}` in trait `{$trait_name}` + +hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind} + .label = not allowed in type signatures + +hir_analysis_associated_type_trait_uninferred_generic_params = cannot use the associated type of a trait with uninferred generic parameters + .suggestion = use a fully qualified path with inferred lifetimes + +hir_analysis_associated_type_trait_uninferred_generic_params_multipart_suggestion = use a fully qualified path with explicit lifetimes + +hir_analysis_enum_discriminant_overflowed = enum discriminant overflowed + .label = overflowed on value after {$discr} + .note = explicitly set `{$item_name} = {$wrapped_discr}` if that is desired outcome + +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 + +hir_analysis_must_implement_one_of_attribute = the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args + +hir_analysis_must_be_name_of_associated_function = must be a name of an associated function + +hir_analysis_function_not_have_default_implementation = function doesn't have a default implementation + .note = required by this annotation + +hir_analysis_must_implement_not_function = not a function + +hir_analysis_must_implement_not_function_span_note = required by this annotation + +hir_analysis_must_implement_not_function_note = all `#[rustc_must_implement_one_of]` arguments must be associated function names + +hir_analysis_function_not_found_in_trait = function not found in this trait + +hir_analysis_functions_names_duplicated = functions names are duplicated + .note = all `#[rustc_must_implement_one_of]` arguments must be unique + +hir_analysis_simd_ffi_highly_experimental = use of SIMD type{$snip} in FFI is highly experimental and may result in invalid code + .help = add `#![feature(simd_ffi)]` to the crate attributes to enable diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs index c49e4d9d5..113c3f08a 100644 --- a/compiler/rustc_hir_analysis/src/astconv/errors.rs +++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs @@ -1,10 +1,14 @@ use crate::astconv::AstConv; -use crate::errors::{ManualImplementation, MissingTypeParams}; +use crate::errors::{ + AssocTypeBindingNotAllowed, ManualImplementation, MissingTypeParams, + ParenthesizedFnTraitExpansion, +}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{pluralize, struct_span_err, Applicability, Diagnostic, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_infer::traits::FulfillmentError; +use rustc_middle::ty::TyCtxt; use rustc_middle::ty::{self, Ty}; use rustc_session::parse::feature_err; use rustc_span::edit_distance::find_best_match_for_name; @@ -51,7 +55,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let trait_def = self.tcx().trait_def(trait_def_id); if !trait_def.paren_sugar { - if trait_segment.args().parenthesized { + if trait_segment.args().parenthesized == hir::GenericArgsParentheses::ParenSugar { // For now, require that parenthetical notation be used only with `Fn()` etc. let mut err = feature_err( &self.tcx().sess.parse_sess, @@ -67,7 +71,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let sess = self.tcx().sess; - if !trait_segment.args().parenthesized { + if trait_segment.args().parenthesized != hir::GenericArgsParentheses::ParenSugar { // For now, require that parenthetical notation be used only with `Fn()` etc. let mut err = feature_err( &sess.parse_sess, @@ -78,43 +82,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Do not suggest the other syntax if we are in trait impl: // the desugaring would contain an associated type constraint. if !is_impl { - let args = trait_segment - .args - .as_ref() - .and_then(|args| args.args.get(0)) - .and_then(|arg| match arg { - hir::GenericArg::Type(ty) => match ty.kind { - hir::TyKind::Tup(t) => t - .iter() - .map(|e| sess.source_map().span_to_snippet(e.span)) - .collect::<Result<Vec<_>, _>>() - .map(|a| a.join(", ")), - _ => sess.source_map().span_to_snippet(ty.span), - } - .map(|s| format!("({})", s)) - .ok(), - _ => None, - }) - .unwrap_or_else(|| "()".to_string()); - let ret = trait_segment - .args() - .bindings - .iter() - .find_map(|b| match (b.ident.name == sym::Output, &b.kind) { - (true, hir::TypeBindingKind::Equality { term }) => { - let span = match term { - hir::Term::Ty(ty) => ty.span, - hir::Term::Const(c) => self.tcx().hir().span(c.hir_id), - }; - sess.source_map().span_to_snippet(span).ok() - } - _ => None, - }) - .unwrap_or_else(|| "()".to_string()); err.span_suggestion( span, "use parenthetical notation instead", - format!("{}{} -> {}", trait_segment.ident, args, ret), + fn_trait_to_string(self.tcx(), trait_segment, true), Applicability::MaybeIncorrect, ); } @@ -512,8 +483,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { [segment] if segment.args.is_none() => { trait_bound_spans = vec![segment.ident.span]; associated_types = associated_types - .into_iter() - .map(|(_, items)| (segment.ident.span, items)) + .into_values() + .map(|items| (segment.ident.span, items)) .collect(); } _ => {} @@ -629,3 +600,77 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { err.emit(); } } + +/// Emits an error regarding forbidden type binding associations +pub fn prohibit_assoc_ty_binding( + tcx: TyCtxt<'_>, + span: Span, + segment: Option<(&hir::PathSegment<'_>, Span)>, +) { + tcx.sess.emit_err(AssocTypeBindingNotAllowed { + span, + fn_trait_expansion: if let Some((segment, span)) = segment + && segment.args().parenthesized == hir::GenericArgsParentheses::ParenSugar + { + Some(ParenthesizedFnTraitExpansion { + span, + expanded_type: fn_trait_to_string(tcx, segment, false), + }) + } else { + None + }, + }); +} + +pub(crate) fn fn_trait_to_string( + tcx: TyCtxt<'_>, + trait_segment: &hir::PathSegment<'_>, + parenthesized: bool, +) -> String { + let args = trait_segment + .args + .as_ref() + .and_then(|args| args.args.get(0)) + .and_then(|arg| match arg { + hir::GenericArg::Type(ty) => match ty.kind { + hir::TyKind::Tup(t) => t + .iter() + .map(|e| tcx.sess.source_map().span_to_snippet(e.span)) + .collect::<Result<Vec<_>, _>>() + .map(|a| a.join(", ")), + _ => tcx.sess.source_map().span_to_snippet(ty.span), + } + .map(|s| { + // `s.empty()` checks to see if the type is the unit tuple, if so we don't want a comma + if parenthesized || s.is_empty() { format!("({})", s) } else { format!("({},)", s) } + }) + .ok(), + _ => None, + }) + .unwrap_or_else(|| "()".to_string()); + + let ret = trait_segment + .args() + .bindings + .iter() + .find_map(|b| match (b.ident.name == sym::Output, &b.kind) { + (true, hir::TypeBindingKind::Equality { term }) => { + let span = match term { + hir::Term::Ty(ty) => ty.span, + hir::Term::Const(c) => tcx.hir().span(c.hir_id), + }; + + (span != tcx.hir().span(trait_segment.hir_id)) + .then_some(tcx.sess.source_map().span_to_snippet(span).ok()) + .flatten() + } + _ => None, + }) + .unwrap_or_else(|| "()".to_string()); + + if parenthesized { + format!("{}{} -> {}", trait_segment.ident, args, ret) + } else { + format!("{}<{}, Output={}>", trait_segment.ident, args, ret) + } +} diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs index 7f6518ffd..3b5c67de2 100644 --- a/compiler/rustc_hir_analysis/src/astconv/generics.rs +++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs @@ -1,9 +1,8 @@ use super::IsMethodCall; use crate::astconv::{ - CreateSubstsForGenericArgsCtxt, ExplicitLateBound, GenericArgCountMismatch, - GenericArgCountResult, GenericArgPosition, + errors::prohibit_assoc_ty_binding, CreateSubstsForGenericArgsCtxt, ExplicitLateBound, + GenericArgCountMismatch, GenericArgCountResult, GenericArgPosition, }; -use crate::errors::AssocTypeBindingNotAllowed; use crate::structured_errors::{GenericArgsInfo, StructuredDiagnostic, WrongNumberOfGenericArgs}; use rustc_ast::ast::ParamKindOrd; use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan}; @@ -433,7 +432,7 @@ pub(crate) fn check_generic_arg_count( (gen_pos != GenericArgPosition::Type || infer_args) && !gen_args.has_lifetime_params(); if gen_pos != GenericArgPosition::Type && let Some(b) = gen_args.bindings.first() { - prohibit_assoc_ty_binding(tcx, b.span); + prohibit_assoc_ty_binding(tcx, b.span, None); } let explicit_late_bound = @@ -589,11 +588,6 @@ pub(crate) fn check_generic_arg_count( } } -/// Emits an error regarding forbidden type binding associations -pub fn prohibit_assoc_ty_binding(tcx: TyCtxt<'_>, span: Span) { - tcx.sess.emit_err(AssocTypeBindingNotAllowed { span }); -} - /// Prohibits explicit lifetime arguments if late-bound lifetime parameters /// are present. This is used both for datatypes and function calls. pub(crate) fn prohibit_explicit_late_bound_lifetimes( @@ -618,7 +612,7 @@ pub(crate) fn prohibit_explicit_late_bound_lifetimes( if position == GenericArgPosition::Value && args.num_lifetime_params() != param_counts.lifetimes { - let mut err = tcx.sess.struct_span_err(span, msg); + let mut err = struct_span_err!(tcx.sess, span, E0794, "{}", msg); err.span_note(span_late, note); err.emit(); } else { diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index f5ce02c9e..8d1156c17 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -5,9 +5,8 @@ mod errors; pub mod generics; -use crate::astconv::generics::{ - check_generic_arg_count, create_substs_for_generic_args, prohibit_assoc_ty_binding, -}; +use crate::astconv::errors::prohibit_assoc_ty_binding; +use crate::astconv::generics::{check_generic_arg_count, create_substs_for_generic_args}; use crate::bounds::Bounds; use crate::collect::HirPlaceholderCollector; use crate::errors::{ @@ -32,10 +31,11 @@ use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::ObligationCause; use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; use rustc_middle::middle::stability::AllowUnstable; +use rustc_middle::ty::fold::FnMutDelegate; use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, SubstsRef}; -use rustc_middle::ty::DynKind; use rustc_middle::ty::GenericParamDefKind; -use rustc_middle::ty::{self, Const, DefIdTree, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, Const, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{DynKind, ToPredicate}; use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, BARE_TRAIT_OBJECTS}; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::edition::Edition; @@ -76,7 +76,7 @@ pub trait AstConv<'tcx> { fn get_type_parameter_bounds( &self, span: Span, - def_id: DefId, + def_id: LocalDefId, assoc_name: Ident, ) -> ty::GenericPredicates<'tcx>; @@ -295,7 +295,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ty::BoundConstness::NotConst, ); if let Some(b) = item_segment.args().bindings.first() { - prohibit_assoc_ty_binding(self.tcx(), b.span); + prohibit_assoc_ty_binding(self.tcx(), b.span, Some((item_segment, span))); } substs @@ -631,7 +631,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ); if let Some(b) = item_segment.args().bindings.first() { - prohibit_assoc_ty_binding(self.tcx(), b.span); + prohibit_assoc_ty_binding(self.tcx(), b.span, Some((item_segment, span))); } args @@ -825,7 +825,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { constness, ); if let Some(b) = trait_segment.args().bindings.first() { - prohibit_assoc_ty_binding(self.tcx(), b.span); + prohibit_assoc_ty_binding(self.tcx(), b.span, Some((trait_segment, span))); } self.tcx().mk_trait_ref(trait_def_id, substs) } @@ -854,16 +854,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ) } - fn trait_defines_associated_type_named(&self, trait_def_id: DefId, assoc_name: Ident) -> bool { - self.tcx() - .associated_items(trait_def_id) - .find_by_name_and_kind(self.tcx(), assoc_name, ty::AssocKind::Type, trait_def_id) - .is_some() - } - fn trait_defines_associated_const_named(&self, trait_def_id: DefId, assoc_name: Ident) -> bool { + fn trait_defines_associated_item_named( + &self, + trait_def_id: DefId, + assoc_kind: ty::AssocKind, + assoc_name: Ident, + ) -> bool { self.tcx() .associated_items(trait_def_id) - .find_by_name_and_kind(self.tcx(), assoc_name, ty::AssocKind::Const, trait_def_id) + .find_by_name_and_kind(self.tcx(), assoc_name, assoc_kind, trait_def_id) .is_some() } @@ -1087,24 +1086,44 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let tcx = self.tcx(); - let candidate = - if self.trait_defines_associated_type_named(trait_ref.def_id(), binding.item_name) { - // Simple case: X is defined in the current trait. + let return_type_notation = + binding.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation; + + let candidate = if return_type_notation { + if self.trait_defines_associated_item_named( + trait_ref.def_id(), + ty::AssocKind::Fn, + binding.item_name, + ) { trait_ref } else { - // Otherwise, we have to walk through the supertraits to find - // those that do. - self.one_bound_for_assoc_type( - || traits::supertraits(tcx, trait_ref), - trait_ref.print_only_trait_path(), - binding.item_name, - path_span, - match binding.kind { - ConvertedBindingKind::Equality(term) => Some(term), - _ => None, - }, - )? - }; + return Err(tcx.sess.emit_err(crate::errors::ReturnTypeNotationMissingMethod { + span: binding.span, + trait_name: tcx.item_name(trait_ref.def_id()), + assoc_name: binding.item_name.name, + })); + } + } else if self.trait_defines_associated_item_named( + trait_ref.def_id(), + ty::AssocKind::Type, + binding.item_name, + ) { + // Simple case: X is defined in the current trait. + trait_ref + } else { + // Otherwise, we have to walk through the supertraits to find + // those that do. + self.one_bound_for_assoc_type( + || traits::supertraits(tcx, trait_ref), + trait_ref.print_only_trait_path(), + binding.item_name, + path_span, + match binding.kind { + ConvertedBindingKind::Equality(term) => Some(term), + _ => None, + }, + )? + }; let (assoc_ident, def_scope) = tcx.adjust_ident_and_get_scope(binding.item_name, candidate.def_id(), hir_ref_id); @@ -1116,9 +1135,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .filter_by_name_unhygienic(assoc_ident.name) .find(|i| i.kind == kind && i.ident(tcx).normalize_to_macros_2_0() == assoc_ident) }; - let assoc_item = find_item_of_kind(ty::AssocKind::Type) - .or_else(|| find_item_of_kind(ty::AssocKind::Const)) - .expect("missing associated type"); + let assoc_item = if return_type_notation { + find_item_of_kind(ty::AssocKind::Fn) + } else { + find_item_of_kind(ty::AssocKind::Type) + .or_else(|| find_item_of_kind(ty::AssocKind::Const)) + } + .expect("missing associated type"); if !assoc_item.visibility(tcx).is_accessible_from(def_scope, tcx) { tcx.sess @@ -1135,7 +1158,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { dup_bindings .entry(assoc_item.def_id) .and_modify(|prev_span| { - self.tcx().sess.emit_err(ValueOfAssociatedStructAlreadySpecified { + tcx.sess.emit_err(ValueOfAssociatedStructAlreadySpecified { span: binding.span, prev_span: *prev_span, item_name: binding.item_name, @@ -1145,28 +1168,100 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .or_insert(binding.span); } - // Include substitutions for generic parameters of associated types - let projection_ty = candidate.map_bound(|trait_ref| { - let ident = Ident::new(assoc_item.name, binding.item_name.span); - let item_segment = hir::PathSegment { - ident, - hir_id: binding.hir_id, - res: Res::Err, - args: Some(binding.gen_args), - infer_args: false, + let projection_ty = if return_type_notation { + // If we have an method return type bound, then we need to substitute + // the method's early bound params with suitable late-bound params. + let mut num_bound_vars = candidate.bound_vars().len(); + let substs = + candidate.skip_binder().substs.extend_to(tcx, assoc_item.def_id, |param, _| { + let subst = match param.kind { + GenericParamDefKind::Lifetime => tcx + .mk_re_late_bound( + ty::INNERMOST, + ty::BoundRegion { + var: ty::BoundVar::from_usize(num_bound_vars), + kind: ty::BoundRegionKind::BrNamed(param.def_id, param.name), + }, + ) + .into(), + GenericParamDefKind::Type { .. } => tcx + .mk_bound( + ty::INNERMOST, + ty::BoundTy { + var: ty::BoundVar::from_usize(num_bound_vars), + kind: ty::BoundTyKind::Param(param.def_id, param.name), + }, + ) + .into(), + GenericParamDefKind::Const { .. } => { + let ty = tcx + .type_of(param.def_id) + .no_bound_vars() + .expect("ct params cannot have early bound vars"); + tcx.mk_const( + ty::ConstKind::Bound( + ty::INNERMOST, + ty::BoundVar::from_usize(num_bound_vars), + ), + ty, + ) + .into() + } + }; + num_bound_vars += 1; + subst + }); + + // Next, we need to check that the return-type notation is being used on + // an RPITIT (return-position impl trait in trait) or AFIT (async fn in trait). + let output = tcx.fn_sig(assoc_item.def_id).skip_binder().output(); + let output = if let ty::Alias(ty::Projection, alias_ty) = *output.skip_binder().kind() + && tcx.def_kind(alias_ty.def_id) == DefKind::ImplTraitPlaceholder + { + alias_ty + } else { + return Err(self.tcx().sess.emit_err( + crate::errors::ReturnTypeNotationOnNonRpitit { + span: binding.span, + ty: tcx.liberate_late_bound_regions(assoc_item.def_id, output), + fn_span: tcx.hir().span_if_local(assoc_item.def_id), + note: (), + }, + )); }; - let substs_trait_ref_and_assoc_item = self.create_substs_for_associated_item( - path_span, - assoc_item.def_id, - &item_segment, - trait_ref.substs, - ); + // Finally, move the fn return type's bound vars over to account for the early bound + // params (and trait ref's late bound params). This logic is very similar to + // `Predicate::subst_supertrait`, and it's no coincidence why. + let shifted_output = tcx.shift_bound_var_indices(num_bound_vars, output); + let subst_output = ty::EarlyBinder(shifted_output).subst(tcx, substs); + + let bound_vars = tcx.late_bound_vars(binding.hir_id); + ty::Binder::bind_with_vars(subst_output, bound_vars) + } else { + // Include substitutions for generic parameters of associated types + candidate.map_bound(|trait_ref| { + let ident = Ident::new(assoc_item.name, binding.item_name.span); + let item_segment = hir::PathSegment { + ident, + hir_id: binding.hir_id, + res: Res::Err, + args: Some(binding.gen_args), + infer_args: false, + }; + + let substs_trait_ref_and_assoc_item = self.create_substs_for_associated_item( + path_span, + assoc_item.def_id, + &item_segment, + trait_ref.substs, + ); - debug!(?substs_trait_ref_and_assoc_item); + debug!(?substs_trait_ref_and_assoc_item); - self.tcx().mk_alias_ty(assoc_item.def_id, substs_trait_ref_and_assoc_item) - }); + tcx.mk_alias_ty(assoc_item.def_id, substs_trait_ref_and_assoc_item) + }) + }; if !speculative { // Find any late-bound regions declared in `ty` that are not @@ -1206,6 +1301,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } match binding.kind { + ConvertedBindingKind::Equality(..) if return_type_notation => { + return Err(self.tcx().sess.emit_err( + crate::errors::ReturnTypeNotationEqualityBound { span: binding.span }, + )); + } ConvertedBindingKind::Equality(mut term) => { // "Desugar" a constraint like `T: Iterator<Item = u32>` this to // the "projection predicate" for: @@ -1267,7 +1367,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty` // parameter to have a skipped binder. let param_ty = tcx.mk_alias(ty::Projection, projection_ty.skip_binder()); - self.add_bounds(param_ty, ast_bounds.iter(), bounds, candidate.bound_vars()); + self.add_bounds(param_ty, ast_bounds.iter(), bounds, projection_ty.bound_vars()); } } Ok(()) @@ -1336,7 +1436,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ty::Clause::RegionOutlives(_) | ty::Clause::ConstArgHasType(..) => bug!(), }, ty::PredicateKind::WellFormed(_) - | ty::PredicateKind::AliasEq(..) + | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::ObjectSafe(_) | ty::PredicateKind::ClosureKind(_, _, _) | ty::PredicateKind::Subtype(_) @@ -1426,14 +1526,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { for (base_trait_ref, span, constness) in regular_traits_refs_spans { assert_eq!(constness, ty::BoundConstness::NotConst); + let base_pred: ty::Predicate<'tcx> = base_trait_ref.to_predicate(tcx); + for pred in traits::elaborate(tcx, [base_pred]) { + debug!("conv_object_ty_poly_trait_ref: observing object predicate `{:?}`", pred); - for obligation in traits::elaborate_trait_ref(tcx, base_trait_ref) { - debug!( - "conv_object_ty_poly_trait_ref: observing object predicate `{:?}`", - obligation.predicate - ); - - let bound_predicate = obligation.predicate.kind(); + let bound_predicate = pred.kind(); match bound_predicate.skip_binder() { ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => { let pred = bound_predicate.rebind(pred); @@ -1441,6 +1538,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { tcx.associated_items(pred.def_id()) .in_definition_order() .filter(|item| item.kind == ty::AssocKind::Type) + .filter(|item| tcx.opt_rpitit_info(item.def_id).is_none()) .map(|item| item.def_id), ); } @@ -1565,39 +1663,45 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }) }); - let existential_projections = projection_bounds.iter().map(|(bound, _)| { - bound.map_bound(|mut b| { - assert_eq!(b.projection_ty.self_ty(), dummy_self); - - // Like for trait refs, verify that `dummy_self` did not leak inside default type - // parameters. - let references_self = b.projection_ty.substs.iter().skip(1).any(|arg| { - if arg.walk().any(|arg| arg == dummy_self.into()) { - return true; + let existential_projections = projection_bounds + .iter() + // We filter out traits that don't have `Self` as their self type above, + // we need to do the same for projections. + .filter(|(bound, _)| bound.skip_binder().self_ty() == dummy_self) + .map(|(bound, _)| { + bound.map_bound(|mut b| { + assert_eq!(b.projection_ty.self_ty(), dummy_self); + + // Like for trait refs, verify that `dummy_self` did not leak inside default type + // parameters. + let references_self = b.projection_ty.substs.iter().skip(1).any(|arg| { + if arg.walk().any(|arg| arg == dummy_self.into()) { + return true; + } + false + }); + if references_self { + let guar = tcx.sess.delay_span_bug( + span, + "trait object projection bounds reference `Self`", + ); + let substs: Vec<_> = b + .projection_ty + .substs + .iter() + .map(|arg| { + if arg.walk().any(|arg| arg == dummy_self.into()) { + return tcx.ty_error(guar).into(); + } + arg + }) + .collect(); + b.projection_ty.substs = tcx.mk_substs(&substs); } - false - }); - if references_self { - let guar = tcx - .sess - .delay_span_bug(span, "trait object projection bounds reference `Self`"); - let substs: Vec<_> = b - .projection_ty - .substs - .iter() - .map(|arg| { - if arg.walk().any(|arg| arg == dummy_self.into()) { - return tcx.ty_error(guar).into(); - } - arg - }) - .collect(); - b.projection_ty.substs = tcx.mk_substs(&substs); - } - ty::ExistentialProjection::erase_self_ty(tcx, b) - }) - }); + ty::ExistentialProjection::erase_self_ty(tcx, b) + }) + }); let regular_trait_predicates = existential_trait_refs .map(|trait_ref| trait_ref.map_bound(ty::ExistentialPredicate::Trait)); @@ -1773,9 +1877,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ty_param_def_id, assoc_name, span, ); - let predicates = &self - .get_type_parameter_bounds(span, ty_param_def_id.to_def_id(), assoc_name) - .predicates; + let predicates = + &self.get_type_parameter_bounds(span, ty_param_def_id, assoc_name).predicates; debug!("find_bound_for_assoc_item: predicates={:#?}", predicates); @@ -1811,10 +1914,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { where I: Iterator<Item = ty::PolyTraitRef<'tcx>>, { - let mut matching_candidates = all_candidates() - .filter(|r| self.trait_defines_associated_type_named(r.def_id(), assoc_name)); - let mut const_candidates = all_candidates() - .filter(|r| self.trait_defines_associated_const_named(r.def_id(), assoc_name)); + let mut matching_candidates = all_candidates().filter(|r| { + self.trait_defines_associated_item_named(r.def_id(), ty::AssocKind::Type, assoc_name) + }); + let mut const_candidates = all_candidates().filter(|r| { + self.trait_defines_associated_item_named(r.def_id(), ty::AssocKind::Const, assoc_name) + }); let (bound, next_cand) = match (matching_candidates.next(), const_candidates.next()) { (Some(bound), _) => (bound, matching_candidates.next()), @@ -2226,47 +2331,66 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let param_env = tcx.param_env(block.owner.to_def_id()); let cause = ObligationCause::misc(span, block.owner.def_id); + let mut fulfillment_errors = Vec::new(); - let mut applicable_candidates: Vec<_> = candidates - .iter() - .filter_map(|&(impl_, (assoc_item, def_scope))| { - infcx.probe(|_| { - let ocx = ObligationCtxt::new_in_snapshot(&infcx); + let mut applicable_candidates: Vec<_> = infcx.probe(|_| { + let universe = infcx.create_next_universe(); + + // Regions are not considered during selection. + let self_ty = tcx.replace_escaping_bound_vars_uncached( + self_ty, + FnMutDelegate { + regions: &mut |_| tcx.lifetimes.re_erased, + types: &mut |bv| { + tcx.mk_placeholder(ty::PlaceholderType { universe, bound: bv }) + }, + consts: &mut |bv, ty| { + tcx.mk_const(ty::PlaceholderConst { universe, bound: bv }, ty) + }, + }, + ); - let impl_ty = tcx.type_of(impl_); - let impl_substs = infcx.fresh_item_substs(impl_); - let impl_ty = impl_ty.subst(tcx, impl_substs); - let impl_ty = ocx.normalize(&cause, param_env, impl_ty); + candidates + .iter() + .filter_map(|&(impl_, (assoc_item, def_scope))| { + infcx.probe(|_| { + let ocx = ObligationCtxt::new_in_snapshot(&infcx); - // Check that the Self-types can be related. - // FIXME(fmease): Should we use `eq` here? - ocx.sup(&ObligationCause::dummy(), param_env, impl_ty, self_ty).ok()?; + let impl_ty = tcx.type_of(impl_); + let impl_substs = infcx.fresh_item_substs(impl_); + let impl_ty = impl_ty.subst(tcx, impl_substs); + let impl_ty = ocx.normalize(&cause, param_env, impl_ty); - // Check whether the impl imposes obligations we have to worry about. - let impl_bounds = tcx.predicates_of(impl_); - let impl_bounds = impl_bounds.instantiate(tcx, impl_substs); + // Check that the Self-types can be related. + // FIXME(fmease): Should we use `eq` here? + ocx.sup(&ObligationCause::dummy(), param_env, impl_ty, self_ty).ok()?; - let impl_bounds = ocx.normalize(&cause, param_env, impl_bounds); + // Check whether the impl imposes obligations we have to worry about. + let impl_bounds = tcx.predicates_of(impl_); + let impl_bounds = impl_bounds.instantiate(tcx, impl_substs); - let impl_obligations = traits::predicates_for_generics( - |_, _| cause.clone(), - param_env, - impl_bounds, - ); + let impl_bounds = ocx.normalize(&cause, param_env, impl_bounds); - ocx.register_obligations(impl_obligations); + let impl_obligations = traits::predicates_for_generics( + |_, _| cause.clone(), + param_env, + impl_bounds, + ); - let mut errors = ocx.select_where_possible(); - if !errors.is_empty() { - fulfillment_errors.append(&mut errors); - return None; - } + ocx.register_obligations(impl_obligations); + + let mut errors = ocx.select_where_possible(); + if !errors.is_empty() { + fulfillment_errors.append(&mut errors); + return None; + } - // FIXME(fmease): Unsolved vars can escape this InferCtxt snapshot. - Some((assoc_item, def_scope, infcx.resolve_vars_if_possible(impl_substs))) + // FIXME(fmease): Unsolved vars can escape this InferCtxt snapshot. + Some((assoc_item, def_scope, infcx.resolve_vars_if_possible(impl_substs))) + }) }) - }) - .collect(); + .collect() + }); if applicable_candidates.len() > 1 { return Err(self.complain_about_ambiguous_inherent_assoc_type( @@ -2396,13 +2520,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { tcx, infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id), ); + let value = tcx.fold_regions(qself_ty, |_, _| tcx.lifetimes.re_erased); + // FIXME: Don't bother dealing with non-lifetime binders here... + if value.has_escaping_bound_vars() { + return false; + } infcx .can_eq( ty::ParamEnv::empty(), impl_.self_ty(), - // Must fold past escaping bound vars too, - // since we have those at this point in astconv. - tcx.fold_regions(qself_ty, |_, _| tcx.lifetimes.re_erased), + value, ) }) && tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative @@ -2451,7 +2578,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { tcx.all_impls(trait_def_id) .filter(|impl_def_id| { // Consider only accessible traits - tcx.visibility(*impl_def_id).is_accessible_from(self.item_def_id(), tcx) + tcx.visibility(trait_def_id).is_accessible_from(self.item_def_id(), tcx) && tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative }) .filter_map(|impl_def_id| tcx.impl_trait_ref(impl_def_id)) @@ -2596,7 +2723,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { for segment in segments { // Only emit the first error to avoid overloading the user with error messages. if let Some(b) = segment.args().bindings.first() { - prohibit_assoc_ty_binding(self.tcx(), b.span); + prohibit_assoc_ty_binding(self.tcx(), b.span, None); return true; } } @@ -3049,10 +3176,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } &hir::TyKind::OpaqueDef(item_id, lifetimes, in_trait) => { let opaque_ty = tcx.hir().item(item_id); - let def_id = item_id.owner_id.to_def_id(); match opaque_ty.kind { hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => { + let local_def_id = item_id.owner_id.def_id; + // If this is an RPITIT and we are using the new RPITIT lowering scheme, we + // generate the def_id of an associated type for the trait and return as + // type a projection. + let def_id = if in_trait && tcx.lower_impl_trait_in_trait_to_assoc_ty() { + tcx.associated_type_for_impl_trait_in_trait(local_def_id).to_def_id() + } else { + local_def_id.to_def_id() + }; self.impl_trait_ty_to_ty(def_id, lifetimes, origin, in_trait) } ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i), @@ -3133,8 +3268,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { debug!("impl_trait_ty_to_ty: generics={:?}", generics); let substs = InternalSubsts::for_item(tcx, def_id, |param, _| { - if let Some(i) = (param.index as usize).checked_sub(generics.parent_count) { - // Our own parameters are the resolved lifetimes. + // We use `generics.count() - lifetimes.len()` here instead of `generics.parent_count` + // since return-position impl trait in trait squashes all of the generics from its source fn + // into its own generics, so the opaque's "own" params isn't always just lifetimes. + if let Some(i) = (param.index as usize).checked_sub(generics.count() - lifetimes.len()) + { + // Resolve our own lifetime parameters. let GenericParamDefKind::Lifetime { .. } = param.kind else { bug!() }; let hir::GenericArg::Lifetime(lifetime) = &lifetimes[i] else { bug!() }; self.ast_region_to_region(lifetime, None).into() @@ -3309,10 +3448,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { tcx, trait_ref.substs.extend_to(tcx, assoc.def_id, |param, _| tcx.mk_param_from_def(param)), ); + let fn_sig = tcx.liberate_late_bound_regions(fn_hir_id.expect_owner().to_def_id(), fn_sig); - let ty = if let Some(arg_idx) = arg_idx { fn_sig.input(arg_idx) } else { fn_sig.output() }; - - Some(tcx.liberate_late_bound_regions(fn_hir_id.expect_owner().to_def_id(), ty)) + Some(if let Some(arg_idx) = arg_idx { + *fn_sig.inputs().get(arg_idx)? + } else { + fn_sig.output() + }) } #[instrument(level = "trace", skip(self, generate_err))] diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs index 0880c8c15..284b099e7 100644 --- a/compiler/rustc_hir_analysis/src/bounds.rs +++ b/compiler/rustc_hir_analysis/src/bounds.rs @@ -58,7 +58,7 @@ impl<'tcx> Bounds<'tcx> { pub fn push_sized(&mut self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) { let sized_def_id = tcx.require_lang_item(LangItem::Sized, Some(span)); let trait_ref = ty::Binder::dummy(tcx.mk_trait_ref(sized_def_id, [ty])); - // Preferrable to put this obligation first, since we report better errors for sized ambiguity. + // Preferable to put this obligation first, since we report better errors for sized ambiguity. self.predicates.insert(0, (trait_ref.without_const().to_predicate(tcx), span)); } diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 848828175..0bb98fdf2 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -1,5 +1,5 @@ use crate::check::intrinsicck::InlineAsmCtxt; -use crate::errors::LinkageType; +use crate::errors::{self, LinkageType}; use super::compare_impl_item::check_type_bounds; use super::compare_impl_item::{compare_impl_method, compare_impl_ty}; @@ -22,12 +22,12 @@ use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES}; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::util::{Discr, IntTypeExt}; use rustc_middle::ty::{ - self, AdtDef, DefIdTree, ParamEnv, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, - TypeVisitableExt, + self, AdtDef, ParamEnv, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, }; use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS}; use rustc_span::symbol::sym; use rustc_span::{self, Span}; +use rustc_target::abi::FieldIdx; use rustc_target::spec::abi::Abi; use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedDirective; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _; @@ -115,9 +115,11 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b allowed_union_field(*elem, tcx, param_env) } _ => { - // Fallback case: allow `ManuallyDrop` and things that are `Copy`. + // Fallback case: allow `ManuallyDrop` and things that are `Copy`, + // also no need to report an error if the type is unresolved. ty.ty_adt_def().is_some_and(|adt_def| adt_def.is_manually_drop()) || ty.is_copy_modulo_regions(tcx, param_env) + || ty.references_error() } } } @@ -132,26 +134,14 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b Some(Node::Field(field)) => (field.span, field.ty.span), _ => unreachable!("mir field has to correspond to hir field"), }; - struct_span_err!( - tcx.sess, + tcx.sess.emit_err(errors::InvalidUnionField { field_span, - E0740, - "unions cannot contain fields that may need dropping" - ) - .note( - "a type is guaranteed not to need dropping \ - when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type", - ) - .multipart_suggestion_verbose( - "when the type does not implement `Copy`, \ - wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped", - vec![ - (ty_span.shrink_to_lo(), "std::mem::ManuallyDrop<".into()), - (ty_span.shrink_to_hi(), ">".into()), - ], - Applicability::MaybeIncorrect, - ) - .emit(); + sugg: errors::InvalidUnionFieldSuggestion { + lo: ty_span.shrink_to_lo(), + hi: ty_span.shrink_to_hi(), + }, + note: (), + }); return false; } else if field_ty.needs_drop(tcx, param_env) { // This should never happen. But we can get here e.g. in case of name resolution errors. @@ -222,7 +212,7 @@ fn check_opaque(tcx: TyCtxt<'_>, id: hir::ItemId) { return; } - let substs = InternalSubsts::identity_for_item(tcx, item.owner_id.to_def_id()); + let substs = InternalSubsts::identity_for_item(tcx, item.owner_id); let span = tcx.def_span(item.owner_id.def_id); if !tcx.features().impl_trait_projections { @@ -315,8 +305,8 @@ pub(super) fn check_opaque_for_inheriting_lifetimes( .. }) = item.kind { - let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id()); - let opaque_identity_ty = if in_trait { + let substs = InternalSubsts::identity_for_item(tcx, def_id); + let opaque_identity_ty = if in_trait && !tcx.lower_impl_trait_in_trait_to_assoc_ty() { tcx.mk_projection(def_id.to_def_id(), substs) } else { tcx.mk_opaque(def_id.to_def_id(), substs) @@ -455,18 +445,15 @@ fn check_opaque_meets_bounds<'tcx>( // version. let errors = ocx.select_all_or_error(); if !errors.is_empty() { - infcx.err_ctxt().report_fulfillment_errors(&errors, None); + infcx.err_ctxt().report_fulfillment_errors(&errors); } match origin { // Checked when type checking the function containing them. hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => {} // Can have different predicates to their defining use hir::OpaqueTyOrigin::TyAlias => { - let outlives_environment = OutlivesEnvironment::new(param_env); - let _ = infcx.err_ctxt().check_region_obligations_and_report_errors( - defining_use_anchor, - &outlives_environment, - ); + let outlives_env = OutlivesEnvironment::new(param_env); + let _ = ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env); } } // Clean up after ourselves @@ -485,7 +472,7 @@ fn is_enum_of_nonnullable_ptr<'tcx>( let [var_one, var_two] = &adt_def.variants().raw[..] else { return false; }; - let (([], [field]) | ([field], [])) = (&var_one.fields[..], &var_two.fields[..]) else { + let (([], [field]) | ([field], [])) = (&var_one.fields.raw[..], &var_two.fields.raw[..]) else { return false; }; matches!(field.ty(tcx, substs).kind(), ty::FnPtr(..) | ty::Ref(..)) @@ -546,7 +533,7 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) { } ty::AssocKind::Type if assoc_item.defaultness(tcx).has_value() => { let trait_substs = - InternalSubsts::identity_for_item(tcx, id.owner_id.to_def_id()); + InternalSubsts::identity_for_item(tcx, id.owner_id); let _: Result<_, rustc_errors::ErrorGuaranteed> = check_type_bounds( tcx, assoc_item, @@ -565,10 +552,18 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) { check_union(tcx, id.owner_id.def_id); } DefKind::OpaqueTy => { - check_opaque(tcx, id); + let opaque = tcx.hir().expect_item(id.owner_id.def_id).expect_opaque_ty(); + if let hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id) = opaque.origin + && let hir::Node::TraitItem(trait_item) = tcx.hir().get_by_def_id(fn_def_id) + && let (_, hir::TraitFn::Required(..)) = trait_item.expect_fn() + { + // Skip opaques from RPIT in traits with no default body. + } else { + check_opaque(tcx, id); + } } DefKind::ImplTraitPlaceholder => { - let parent = tcx.impl_trait_in_trait_parent(id.owner_id.to_def_id()); + let parent = tcx.impl_trait_in_trait_parent_fn(id.owner_id.to_def_id()); // Only check the validity of this opaque type if the function has a default body if let hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)), @@ -896,7 +891,7 @@ pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) { struct_span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty").emit(); return; } - let e = fields[0].ty(tcx, substs); + let e = fields[FieldIdx::from_u32(0)].ty(tcx, substs); if !fields.iter().all(|f| f.ty(tcx, substs) == e) { struct_span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous") .span_label(sp, "SIMD elements must have the same type") @@ -1172,7 +1167,7 @@ fn check_enum(tcx: TyCtxt<'_>, def_id: LocalDefId) { def.destructor(tcx); // force the destructor to be evaluated if def.variants().is_empty() { - if let Some(attr) = tcx.get_attrs(def_id.to_def_id(), sym::repr).next() { + if let Some(attr) = tcx.get_attrs(def_id, sym::repr).next() { struct_span_err!( tcx.sess, attr.span, @@ -1511,6 +1506,14 @@ fn opaque_type_cycle_error( { label_match(interior_ty.ty, interior_ty.span); } + if tcx.sess.opts.unstable_opts.drop_tracking_mir + && let DefKind::Generator = tcx.def_kind(closure_def_id) + { + let generator_layout = tcx.mir_generator_witnesses(closure_def_id); + for interior_ty in &generator_layout.field_tys { + label_match(interior_ty.ty, interior_ty.source_info.span); + } + } } } } @@ -1548,6 +1551,6 @@ pub(super) fn check_generator_obligations(tcx: TyCtxt<'_>, def_id: LocalDefId) { let errors = fulfillment_cx.select_all_or_error(&infcx); debug!(?errors); if !errors.is_empty() { - infcx.err_ctxt().report_fulfillment_errors(&errors, None); + infcx.err_ctxt().report_fulfillment_errors(&errors); } } diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 691d3f8d9..5d119a773 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -16,8 +16,7 @@ use rustc_infer::traits::util; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::util::ExplicitSelf; use rustc_middle::ty::{ - self, DefIdTree, InternalSubsts, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, - TypeVisitableExt, + self, InternalSubsts, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, }; use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt}; use rustc_span::Span; @@ -321,7 +320,7 @@ fn compare_method_predicate_entailment<'tcx>( }); } CheckImpliedWfMode::Skip => { - let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None); + let reported = infcx.err_ctxt().report_fulfillment_errors(&errors); return Err(reported); } } @@ -331,13 +330,8 @@ fn compare_method_predicate_entailment<'tcx>( // lifetime parameters. let outlives_env = OutlivesEnvironment::with_bounds( param_env, - Some(infcx), infcx.implied_bounds_tys(param_env, impl_m_def_id, wf_tys.clone()), ); - infcx.process_registered_region_obligations( - outlives_env.region_bound_pairs(), - outlives_env.param_env, - ); let errors = infcx.resolve_regions(&outlives_env); if !errors.is_empty() { // FIXME(compiler-errors): This can be simplified when IMPLIED_BOUNDS_ENTAILMENT @@ -584,13 +578,13 @@ fn compare_asyncness<'tcx>( #[instrument(skip(tcx), level = "debug", ret)] pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( tcx: TyCtxt<'tcx>, - def_id: DefId, + impl_m_def_id: LocalDefId, ) -> Result<&'tcx FxHashMap<DefId, Ty<'tcx>>, ErrorGuaranteed> { - let impl_m = tcx.opt_associated_item(def_id).unwrap(); + let impl_m = tcx.opt_associated_item(impl_m_def_id.to_def_id()).unwrap(); let trait_m = tcx.opt_associated_item(impl_m.trait_item_def_id.unwrap()).unwrap(); let impl_trait_ref = tcx.impl_trait_ref(impl_m.impl_container(tcx).unwrap()).unwrap().subst_identity(); - let param_env = tcx.param_env(def_id); + let param_env = tcx.param_env(impl_m_def_id); // First, check a few of the same things as `compare_impl_method`, // just so we don't ICE during substitution later. @@ -600,7 +594,6 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( let trait_to_impl_substs = impl_trait_ref.substs; - let impl_m_def_id = impl_m.def_id.expect_local(); let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m_def_id); let return_span = tcx.hir().fn_decl_by_hir_id(impl_m_hir_id).unwrap().output.span(); let cause = ObligationCause::new( @@ -721,23 +714,22 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( // RPITs. let errors = ocx.select_all_or_error(); if !errors.is_empty() { - let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None); + let reported = infcx.err_ctxt().report_fulfillment_errors(&errors); return Err(reported); } + let collected_types = collector.types; + // Finally, resolve all regions. This catches wily misuses of // lifetime parameters. - let outlives_environment = OutlivesEnvironment::with_bounds( + let outlives_env = OutlivesEnvironment::with_bounds( param_env, - Some(infcx), infcx.implied_bounds_tys(param_env, impl_m_def_id, wf_tys), ); - infcx - .err_ctxt() - .check_region_obligations_and_report_errors(impl_m_def_id, &outlives_environment)?; + ocx.resolve_regions_and_report_errors(impl_m_def_id, &outlives_env)?; let mut collected_tys = FxHashMap::default(); - for (def_id, (ty, substs)) in collector.types { + for (def_id, (ty, substs)) in collected_types { match infcx.fully_resolve(ty) { Ok(ty) => { // `ty` contains free regions that we created earlier while liberating the @@ -831,7 +823,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx> { fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { if let ty::Alias(ty::Projection, proj) = ty.kind() - && self.interner().def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder + && self.interner().is_impl_trait_in_trait(proj.def_id) { if let Some((ty, _)) = self.types.get(&proj.def_id) { return *ty; @@ -1206,6 +1198,17 @@ fn compare_number_of_generics<'tcx>( return Ok(()); } + // We never need to emit a separate error for RPITITs, since if an RPITIT + // has mismatched type or const generic arguments, then the method that it's + // inheriting the generics from will also have mismatched arguments, and + // we'll report an error for that instead. Delay a bug for safety, though. + if tcx.opt_rpitit_info(trait_.def_id).is_some() { + return Err(tcx.sess.delay_span_bug( + rustc_span::DUMMY_SP, + "errors comparing numbers of generics of trait/impl functions were not emitted", + )); + } + let matchings = [ ("type", trait_own_counts.types, impl_own_counts.types), ("const", trait_own_counts.consts, impl_own_counts.consts), @@ -1732,14 +1735,11 @@ pub(super) fn compare_impl_const_raw( // version. let errors = ocx.select_all_or_error(); if !errors.is_empty() { - return Err(infcx.err_ctxt().report_fulfillment_errors(&errors, None)); + return Err(infcx.err_ctxt().report_fulfillment_errors(&errors)); } - let outlives_environment = OutlivesEnvironment::new(param_env); - infcx - .err_ctxt() - .check_region_obligations_and_report_errors(impl_const_item_def, &outlives_environment)?; - Ok(()) + let outlives_env = OutlivesEnvironment::new(param_env); + ocx.resolve_regions_and_report_errors(impl_const_item_def, &outlives_env) } pub(super) fn compare_impl_ty<'tcx>( @@ -1832,19 +1832,14 @@ fn compare_type_predicate_entailment<'tcx>( // version. let errors = ocx.select_all_or_error(); if !errors.is_empty() { - let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None); + let reported = infcx.err_ctxt().report_fulfillment_errors(&errors); return Err(reported); } // Finally, resolve all regions. This catches wily misuses of // lifetime parameters. - let outlives_environment = OutlivesEnvironment::new(param_env); - infcx.err_ctxt().check_region_obligations_and_report_errors( - impl_ty.def_id.expect_local(), - &outlives_environment, - )?; - - Ok(()) + let outlives_env = OutlivesEnvironment::new(param_env); + ocx.resolve_regions_and_report_errors(impl_ty_def_id, &outlives_env) } /// Validate that `ProjectionCandidate`s created for this associated type will @@ -1867,14 +1862,17 @@ pub(super) fn check_type_bounds<'tcx>( impl_ty: ty::AssocItem, impl_trait_ref: ty::TraitRef<'tcx>, ) -> Result<(), ErrorGuaranteed> { + let param_env = tcx.param_env(impl_ty.def_id); + let container_id = impl_ty.container_id(tcx); // Given // // impl<A, B> Foo<u32> for (A, B) { - // type Bar<C> =... + // type Bar<C> = Wrapper<A, B, C> // } // // - `impl_trait_ref` would be `<(A, B) as Foo<u32>>` - // - `impl_ty_substs` would be `[A, B, ^0.0]` (`^0.0` here is the bound var with db 0 and index 0) + // - `normalize_impl_ty_substs` would be `[A, B, ^0.0]` (`^0.0` here is the bound var with db 0 and index 0) + // - `normalize_impl_ty` would be `Wrapper<A, B, ^0.0>` // - `rebased_substs` would be `[(A, B), u32, ^0.0]`, combining the substs from // the *trait* with the generic associated type parameters (as bound vars). // @@ -1903,56 +1901,46 @@ pub(super) fn check_type_bounds<'tcx>( // Member<C: Eq> = .... That type would fail a well-formedness check that we ought to be doing // elsewhere, which would check that any <T as Family>::Member<X> meets the bounds declared in // the trait (notably, that X: Eq and T: Family). - let defs: &ty::Generics = tcx.generics_of(impl_ty.def_id); - let mut substs = smallvec::SmallVec::with_capacity(defs.count()); - if let Some(def_id) = defs.parent { - let parent_defs = tcx.generics_of(def_id); - InternalSubsts::fill_item(&mut substs, tcx, parent_defs, &mut |param, _| { - tcx.mk_param_from_def(param) - }); - } let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind; 8]> = - smallvec::SmallVec::with_capacity(defs.count()); - InternalSubsts::fill_single(&mut substs, defs, &mut |param, _| match param.kind { - GenericParamDefKind::Type { .. } => { - let kind = ty::BoundTyKind::Param(param.def_id, param.name); - let bound_var = ty::BoundVariableKind::Ty(kind); - bound_vars.push(bound_var); - tcx.mk_bound( - ty::INNERMOST, - ty::BoundTy { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind }, - ) - .into() - } - GenericParamDefKind::Lifetime => { - let kind = ty::BoundRegionKind::BrNamed(param.def_id, param.name); - let bound_var = ty::BoundVariableKind::Region(kind); - bound_vars.push(bound_var); - tcx.mk_re_late_bound( - ty::INNERMOST, - ty::BoundRegion { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind }, - ) - .into() - } - GenericParamDefKind::Const { .. } => { - let bound_var = ty::BoundVariableKind::Const; - bound_vars.push(bound_var); - tcx.mk_const( - ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from_usize(bound_vars.len() - 1)), - tcx.type_of(param.def_id).subst_identity(), - ) - .into() - } - }); - let bound_vars = tcx.mk_bound_variable_kinds(&bound_vars); - let impl_ty_substs = tcx.mk_substs(&substs); - let container_id = impl_ty.container_id(tcx); - - let rebased_substs = impl_ty_substs.rebase_onto(tcx, container_id, impl_trait_ref.substs); - let impl_ty_value = tcx.type_of(impl_ty.def_id).subst_identity(); - - let param_env = tcx.param_env(impl_ty.def_id); - + smallvec::SmallVec::with_capacity(tcx.generics_of(impl_ty.def_id).params.len()); + // Extend the impl's identity substs with late-bound GAT vars + let normalize_impl_ty_substs = ty::InternalSubsts::identity_for_item(tcx, container_id) + .extend_to(tcx, impl_ty.def_id, |param, _| match param.kind { + GenericParamDefKind::Type { .. } => { + let kind = ty::BoundTyKind::Param(param.def_id, param.name); + let bound_var = ty::BoundVariableKind::Ty(kind); + bound_vars.push(bound_var); + tcx.mk_bound( + ty::INNERMOST, + ty::BoundTy { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind }, + ) + .into() + } + GenericParamDefKind::Lifetime => { + let kind = ty::BoundRegionKind::BrNamed(param.def_id, param.name); + let bound_var = ty::BoundVariableKind::Region(kind); + bound_vars.push(bound_var); + tcx.mk_re_late_bound( + ty::INNERMOST, + ty::BoundRegion { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind }, + ) + .into() + } + GenericParamDefKind::Const { .. } => { + let bound_var = ty::BoundVariableKind::Const; + bound_vars.push(bound_var); + tcx.mk_const( + ty::ConstKind::Bound( + ty::INNERMOST, + ty::BoundVar::from_usize(bound_vars.len() - 1), + ), + tcx.type_of(param.def_id) + .no_bound_vars() + .expect("const parameter types cannot be generic"), + ) + .into() + } + }); // When checking something like // // trait X { type Y: PartialEq<<Self as X>::Y> } @@ -1962,9 +1950,13 @@ pub(super) fn check_type_bounds<'tcx>( // we want <T as X>::Y to normalize to S. This is valid because we are // checking the default value specifically here. Add this equality to the // ParamEnv for normalization specifically. + let normalize_impl_ty = tcx.type_of(impl_ty.def_id).subst(tcx, normalize_impl_ty_substs); + let rebased_substs = + normalize_impl_ty_substs.rebase_onto(tcx, container_id, impl_trait_ref.substs); + let bound_vars = tcx.mk_bound_variable_kinds(&bound_vars); let normalize_param_env = { let mut predicates = param_env.caller_bounds().iter().collect::<Vec<_>>(); - match impl_ty_value.kind() { + match normalize_impl_ty.kind() { ty::Alias(ty::Projection, proj) if proj.def_id == trait_ty.def_id && proj.substs == rebased_substs => { @@ -1978,7 +1970,7 @@ pub(super) fn check_type_bounds<'tcx>( ty::Binder::bind_with_vars( ty::ProjectionPredicate { projection_ty: tcx.mk_alias_ty(trait_ty.def_id, rebased_substs), - term: impl_ty_value.into(), + term: normalize_impl_ty.into(), }, bound_vars, ) @@ -1996,13 +1988,20 @@ pub(super) fn check_type_bounds<'tcx>( let infcx = tcx.infer_ctxt().build(); let ocx = ObligationCtxt::new(&infcx); - let impl_ty_span = match tcx.hir().get_by_def_id(impl_ty_def_id) { - hir::Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Type(_, Some(ty)), - .. - }) => ty.span, - hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Type(ty), .. }) => ty.span, - _ => bug!(), + // A synthetic impl Trait for RPITIT desugaring has no HIR, which we currently use to get the + // span for an impl's associated type. Instead, for these, use the def_span for the synthesized + // associated type. + let impl_ty_span = if tcx.opt_rpitit_info(impl_ty.def_id).is_some() { + tcx.def_span(impl_ty_def_id) + } else { + match tcx.hir().get_by_def_id(impl_ty_def_id) { + hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Type(_, Some(ty)), + .. + }) => ty.span, + hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Type(ty), .. }) => ty.span, + _ => bug!(), + } }; let assumed_wf_types = ocx.assumed_wf_types(param_env, impl_ty_span, impl_ty_def_id); @@ -2023,7 +2022,7 @@ pub(super) fn check_type_bounds<'tcx>( ObligationCause::new(impl_ty_span, impl_ty_def_id, code) }; - let obligations = tcx + let obligations: Vec<_> = tcx .bound_explicit_item_bounds(trait_ty.def_id) .subst_iter_copied(tcx, rebased_substs) .map(|(concrete_ty_bound, span)| { @@ -2033,7 +2032,7 @@ pub(super) fn check_type_bounds<'tcx>( .collect(); debug!("check_type_bounds: item_bounds={:?}", obligations); - for mut obligation in util::elaborate_obligations(tcx, obligations) { + for mut obligation in util::elaborate(tcx, obligations) { let normalized_predicate = ocx.normalize(&normalize_cause, normalize_param_env, obligation.predicate); debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate); @@ -2045,22 +2044,15 @@ pub(super) fn check_type_bounds<'tcx>( // version. let errors = ocx.select_all_or_error(); if !errors.is_empty() { - let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None); + let reported = infcx.err_ctxt().report_fulfillment_errors(&errors); return Err(reported); } // Finally, resolve all regions. This catches wily misuses of // lifetime parameters. let implied_bounds = infcx.implied_bounds_tys(param_env, impl_ty_def_id, assumed_wf_types); - let outlives_environment = - OutlivesEnvironment::with_bounds(param_env, Some(&infcx), implied_bounds); - - infcx.err_ctxt().check_region_obligations_and_report_errors( - impl_ty.def_id.expect_local(), - &outlives_environment, - )?; - - Ok(()) + let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); + ocx.resolve_regions_and_report_errors(impl_ty_def_id, &outlives_env) } fn assoc_item_kind_str(impl_item: &ty::AssocItem) -> &'static str { diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs index 2bb724138..111bf5e54 100644 --- a/compiler/rustc_hir_analysis/src/check/dropck.rs +++ b/compiler/rustc_hir_analysis/src/check/dropck.rs @@ -253,10 +253,6 @@ impl<'tcx> TypeRelation<'tcx> for SimpleEqRelation<'tcx> { self.tcx } - fn intercrate(&self) -> bool { - false - } - fn param_env(&self) -> ty::ParamEnv<'tcx> { self.param_env } @@ -269,10 +265,6 @@ impl<'tcx> TypeRelation<'tcx> for SimpleEqRelation<'tcx> { true } - fn mark_ambiguous(&mut self) { - bug!() - } - fn relate_with_variance<T: Relate<'tcx>>( &mut self, _: ty::Variance, diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 054284cce..854974d16 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -59,6 +59,7 @@ fn equate_intrinsic_type<'tcx>( require_same_types( tcx, &cause, + ty::ParamEnv::empty(), // FIXME: do all intrinsics have an empty param env? tcx.mk_fn_ptr(tcx.fn_sig(it.owner_id).subst_identity()), fty, ); @@ -138,14 +139,14 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { let name_str = intrinsic_name.as_str(); let bound_vars = tcx.mk_bound_variable_kinds(&[ - ty::BoundVariableKind::Region(ty::BrAnon(0, None)), + ty::BoundVariableKind::Region(ty::BrAnon(None)), ty::BoundVariableKind::Region(ty::BrEnv), ]); let mk_va_list_ty = |mutbl| { tcx.lang_items().va_list().map(|did| { let region = tcx.mk_re_late_bound( ty::INNERMOST, - ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) }, + ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(None) }, ); let env_region = tcx.mk_re_late_bound( ty::INNERMOST, @@ -222,6 +223,21 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { ], tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }), ), + sym::option_payload_ptr => { + let option_def_id = tcx.require_lang_item(hir::LangItem::Option, None); + let p0 = param(0); + ( + 1, + vec![tcx.mk_ptr(ty::TypeAndMut { + ty: tcx.mk_adt( + tcx.adt_def(option_def_id), + tcx.mk_substs_from_iter([ty::GenericArg::from(p0)].into_iter()), + ), + mutbl: hir::Mutability::Not, + })], + tcx.mk_ptr(ty::TypeAndMut { ty: p0, mutbl: hir::Mutability::Not }), + ) + } sym::ptr_mask => ( 1, vec![ @@ -300,6 +316,8 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { sym::nearbyintf64 => (0, vec![tcx.types.f64], tcx.types.f64), sym::roundf32 => (0, vec![tcx.types.f32], tcx.types.f32), sym::roundf64 => (0, vec![tcx.types.f64], tcx.types.f64), + sym::roundevenf32 => (0, vec![tcx.types.f32], tcx.types.f32), + sym::roundevenf64 => (0, vec![tcx.types.f64], tcx.types.f64), sym::volatile_load | sym::unaligned_volatile_load => { (1, vec![tcx.mk_imm_ptr(param(0))], param(0)) @@ -361,14 +379,15 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { sym::likely => (0, vec![tcx.types.bool], tcx.types.bool), sym::unlikely => (0, vec![tcx.types.bool], tcx.types.bool), + sym::read_via_copy => (1, vec![tcx.mk_imm_ptr(param(0))], param(0)), + sym::discriminant_value => { let assoc_items = tcx.associated_item_def_ids( tcx.require_lang_item(hir::LangItem::DiscriminantKind, None), ); let discriminant_def_id = assoc_items[0]; - let br = - ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) }; + let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(None) }; ( 1, vec![tcx.mk_imm_ref(tcx.mk_re_late_bound(ty::INNERMOST, br), param(0))], @@ -420,8 +439,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { sym::nontemporal_store => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()), sym::raw_eq => { - let br = - ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) }; + let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(None) }; let param_ty = tcx.mk_imm_ref(tcx.mk_re_late_bound(ty::INNERMOST, br), param(0)); (1, vec![param_ty; 2], tcx.types.bool) } diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs index b1d5a27be..0d482b53a 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs @@ -1,10 +1,11 @@ use rustc_ast::InlineAsmTemplatePiece; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::FxIndexSet; use rustc_hir as hir; use rustc_middle::ty::{self, Article, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, UintTy}; use rustc_session::lint; use rustc_span::def_id::LocalDefId; use rustc_span::{Symbol, DUMMY_SP}; +use rustc_target::abi::FieldIdx; use rustc_target::asm::{InlineAsmReg, InlineAsmRegClass, InlineAsmRegOrRegClass, InlineAsmType}; pub struct InlineAsmCtxt<'a, 'tcx> { @@ -51,7 +52,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { template: &[InlineAsmTemplatePiece], is_input: bool, tied_input: Option<(&'tcx hir::Expr<'tcx>, Option<InlineAsmType>)>, - target_features: &FxHashSet<Symbol>, + target_features: &FxIndexSet<Symbol>, ) -> Option<InlineAsmType> { let ty = (self.get_operand_ty)(expr); if ty.has_non_region_infer() { @@ -82,7 +83,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { } ty::Adt(adt, substs) if adt.repr().simd() => { let fields = &adt.non_enum_variant().fields; - let elem_ty = fields[0].ty(self.tcx, substs); + let elem_ty = fields[FieldIdx::from_u32(0)].ty(self.tcx, substs); match elem_ty.kind() { ty::Never | ty::Error(_) => return None, ty::Int(IntTy::I8) | ty::Uint(UintTy::U8) => { @@ -201,7 +202,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { // (!). In that case we still need the earlier check to verify that the // register class is usable at all. if let Some(feature) = feature { - if !target_features.contains(&feature) { + if !target_features.contains(feature) { let msg = &format!("`{}` target feature is not enabled", feature); let mut err = self.tcx.sess.struct_span_err(expr.span, msg); err.note(&format!( diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 9acfc1b3d..8fe4c44fc 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -109,8 +109,8 @@ pub fn provide(providers: &mut Providers) { }; } -fn adt_destructor(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::Destructor> { - tcx.calculate_dtor(def_id, dropck::check_drop_impl) +fn adt_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::Destructor> { + tcx.calculate_dtor(def_id.to_def_id(), dropck::check_drop_impl) } /// Given a `DefId` for an opaque type in return position, find its parent item's return @@ -202,8 +202,11 @@ fn missing_items_err( missing_items: &[ty::AssocItem], full_impl_span: Span, ) { + let missing_items = + missing_items.iter().filter(|trait_item| tcx.opt_rpitit_info(trait_item.def_id).is_none()); + let missing_items_msg = missing_items - .iter() + .clone() .map(|trait_item| trait_item.name.to_string()) .collect::<Vec<_>>() .join("`, `"); diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 4cccdf30c..53197bc84 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1,7 +1,6 @@ use crate::autoderef::Autoderef; use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter}; -use hir::def::DefKind; use rustc_ast as ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed}; @@ -111,16 +110,13 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>( let errors = wfcx.select_all_or_error(); if !errors.is_empty() { - infcx.err_ctxt().report_fulfillment_errors(&errors, None); + infcx.err_ctxt().report_fulfillment_errors(&errors); return; } - let outlives_environment = - OutlivesEnvironment::with_bounds(param_env, Some(infcx), implied_bounds); + let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); - let _ = infcx - .err_ctxt() - .check_region_obligations_and_report_errors(body_def_id, &outlives_environment); + let _ = wfcx.ocx.resolve_regions_and_report_errors(body_def_id, &outlives_env); } fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) { @@ -676,19 +672,13 @@ fn resolve_regions_with_wf_tys<'tcx>( let infcx = tcx.infer_ctxt().build(); let outlives_environment = OutlivesEnvironment::with_bounds( param_env, - Some(&infcx), infcx.implied_bounds_tys(param_env, id, wf_tys.clone()), ); let region_bound_pairs = outlives_environment.region_bound_pairs(); add_constraints(&infcx, region_bound_pairs); - infcx.process_registered_region_obligations( - outlives_environment.region_bound_pairs(), - param_env, - ); let errors = infcx.resolve_regions(&outlives_environment); - debug!(?errors, "errors"); // If we were able to prove that the type outlives the region without @@ -1033,7 +1023,7 @@ fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: b // intermediate types must be sized. let needs_drop_copy = || { packed && { - let ty = tcx.type_of(variant.fields.last().unwrap().did).subst_identity(); + let ty = tcx.type_of(variant.fields.raw.last().unwrap().did).subst_identity(); let ty = tcx.erase_regions(ty); if ty.needs_infer() { tcx.sess @@ -1049,7 +1039,7 @@ fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: b let all_sized = all_sized || variant.fields.is_empty() || needs_drop_copy(); let unsized_len = if all_sized { 0 } else { 1 }; for (idx, field) in - variant.fields[..variant.fields.len() - unsized_len].iter().enumerate() + variant.fields.raw[..variant.fields.len() - unsized_len].iter().enumerate() { let last = idx == variant.fields.len() - 1; let field_id = field.did.expect_local(); @@ -1545,31 +1535,81 @@ fn check_return_position_impl_trait_in_trait_bounds<'tcx>( span: Span, ) { let tcx = wfcx.tcx(); - if let Some(assoc_item) = tcx.opt_associated_item(fn_def_id.to_def_id()) - && assoc_item.container == ty::AssocItemContainer::TraitContainer - { - for arg in fn_output.walk() { - if let ty::GenericArgKind::Type(ty) = arg.unpack() - && let ty::Alias(ty::Opaque, proj) = ty.kind() - && tcx.def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder - && tcx.impl_trait_in_trait_parent(proj.def_id) == fn_def_id.to_def_id() + let Some(assoc_item) = tcx.opt_associated_item(fn_def_id.to_def_id()) else { + return; + }; + if assoc_item.container != ty::AssocItemContainer::TraitContainer { + return; + } + fn_output.visit_with(&mut ImplTraitInTraitFinder { + wfcx, + fn_def_id, + depth: ty::INNERMOST, + seen: FxHashSet::default(), + }); +} + +// FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): Even with the new lowering +// strategy, we can't just call `check_associated_item` on the new RPITITs, +// because tests like `tests/ui/async-await/in-trait/implied-bounds.rs` will fail. +// That's because we need to check that the bounds of the RPITIT hold using +// the special substs that we create during opaque type lowering, otherwise we're +// getting a bunch of early bound and free regions mixed up... Haven't looked too +// deep into this, though. +struct ImplTraitInTraitFinder<'a, 'tcx> { + wfcx: &'a WfCheckingCtxt<'a, 'tcx>, + fn_def_id: LocalDefId, + depth: ty::DebruijnIndex, + seen: FxHashSet<DefId>, +} +impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> { + type BreakTy = !; + + fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<!> { + let tcx = self.wfcx.tcx(); + if let ty::Alias(ty::Opaque, unshifted_opaque_ty) = *ty.kind() + && self.seen.insert(unshifted_opaque_ty.def_id) + && let Some(opaque_def_id) = unshifted_opaque_ty.def_id.as_local() + && let opaque = tcx.hir().expect_item(opaque_def_id).expect_opaque_ty() + && let hir::OpaqueTyOrigin::FnReturn(source) | hir::OpaqueTyOrigin::AsyncFn(source) = opaque.origin + && source == self.fn_def_id + { + let opaque_ty = tcx.fold_regions(unshifted_opaque_ty, |re, depth| { + if let ty::ReLateBound(index, bv) = re.kind() { + if depth != ty::INNERMOST { + return tcx.mk_re_error_with_message( + DUMMY_SP, + "we shouldn't walk non-predicate binders with `impl Trait`...", + ); + } + tcx.mk_re_late_bound(index.shifted_out_to_binder(self.depth), bv) + } else { + re + } + }); + for (bound, bound_span) in tcx + .bound_explicit_item_bounds(opaque_ty.def_id) + .subst_iter_copied(tcx, opaque_ty.substs) { - let span = tcx.def_span(proj.def_id); - let bounds = wfcx.tcx().explicit_item_bounds(proj.def_id); - let wf_obligations = bounds.iter().flat_map(|&(bound, bound_span)| { - let bound = ty::EarlyBinder(bound).subst(tcx, proj.substs); - let normalized_bound = wfcx.normalize(span, None, bound); - traits::wf::predicate_obligations( - wfcx.infcx, - wfcx.param_env, - wfcx.body_def_id, - normalized_bound, - bound_span, - ) - }); - wfcx.register_obligations(wf_obligations); + let bound = self.wfcx.normalize(bound_span, None, bound); + self.wfcx.register_obligations(traits::wf::predicate_obligations( + self.wfcx.infcx, + self.wfcx.param_env, + self.wfcx.body_def_id, + bound, + bound_span, + )); + // Set the debruijn index back to innermost here, since we already eagerly + // shifted the substs that we use to generate these bounds. This is unfortunately + // subtly different behavior than the `ImplTraitInTraitFinder` we use in `param_env`, + // but that function doesn't actually need to normalize the bound it's visiting + // (whereas we have to do so here)... + let old_depth = std::mem::replace(&mut self.depth, ty::INNERMOST); + bound.visit_with(self); + self.depth = old_depth; } } + ty.super_visit_with(self) } } @@ -1784,7 +1824,7 @@ fn check_variances_for_type_defn<'tcx>( // Lazily calculated because it is only needed in case of an error. let explicitly_bounded_params = LazyCell::new(|| { - let icx = crate::collect::ItemCtxt::new(tcx, item.owner_id.to_def_id()); + let icx = crate::collect::ItemCtxt::new(tcx, item.owner_id.def_id); hir_generics .predicates .iter() @@ -1861,16 +1901,15 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> { let predicates_with_span = tcx.predicates_of(self.body_def_id).predicates.iter().copied(); // Check elaborated bounds. - let implied_obligations = traits::elaborate_predicates_with_span(tcx, predicates_with_span); + let implied_obligations = traits::elaborate(tcx, predicates_with_span); - for obligation in implied_obligations { + for (pred, obligation_span) in implied_obligations { // We lower empty bounds like `Vec<dyn Copy>:` as // `WellFormed(Vec<dyn Copy>)`, which will later get checked by // regular WF checking - if let ty::PredicateKind::WellFormed(..) = obligation.predicate.kind().skip_binder() { + if let ty::PredicateKind::WellFormed(..) = pred.kind().skip_binder() { continue; } - let pred = obligation.predicate; // Match the existing behavior. if pred.is_global() && !pred.has_late_bound_vars() { let pred = self.normalize(span, None, pred); @@ -1881,8 +1920,6 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> { if let Some(hir::Generics { predicates, .. }) = hir_node.and_then(|node| node.generics()) { - let obligation_span = obligation.cause.span(); - span = predicates .iter() // There seems to be no better way to find out which predicate we are in diff --git a/compiler/rustc_hir_analysis/src/check_unused.rs b/compiler/rustc_hir_analysis/src/check_unused.rs index f3f5851d8..268b9ac53 100644 --- a/compiler/rustc_hir_analysis/src/check_unused.rs +++ b/compiler/rustc_hir_analysis/src/check_unused.rs @@ -10,7 +10,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) { for item_def_id in tcx.hir().body_owners() { let imports = tcx.used_trait_imports(item_def_id); debug!("GatherVisitor: item_def_id={:?} with imports {:#?}", item_def_id, imports); - used_trait_imports.extend(imports.items().copied()); + used_trait_imports.extend_unord(imports.items().copied()); } for &id in tcx.maybe_unused_trait_imports(()) { diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index ffb68abf9..0f40cca94 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -2,21 +2,23 @@ //! up data structures required by type-checking/codegen. use crate::errors::{CopyImplOnNonAdt, CopyImplOnTypeWithDtor, DropImplOnWrongItem}; +use rustc_data_structures::fx::FxHashSet; use rustc_errors::{struct_span_err, MultiSpan}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::lang_items::LangItem; use rustc_hir::ItemKind; use rustc_infer::infer::outlives::env::OutlivesEnvironment; -use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::{self, RegionResolutionError}; +use rustc_infer::infer::{DefineOpaqueTypes, TyCtxtInferExt}; +use rustc_infer::traits::Obligation; use rustc_middle::ty::adjustment::CoerceUnsizedInfo; use rustc_middle::ty::{self, suggest_constraining_type_params, Ty, TyCtxt, TypeVisitableExt}; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; use rustc_trait_selection::traits::misc::{ type_allowed_to_implement_copy, CopyImplementationError, InfringingFieldsReason, }; -use rustc_trait_selection::traits::predicate_for_trait_def; +use rustc_trait_selection::traits::ObligationCtxt; use rustc_trait_selection::traits::{self, ObligationCause}; use std::collections::BTreeMap; @@ -86,7 +88,7 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) { tcx.sess, span, E0204, - "the trait `Copy` may not be implemented for this type" + "the trait `Copy` cannot be implemented for this type" ); // We'll try to suggest constraining type parameters to fulfill the requirements of @@ -94,7 +96,14 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) { let mut errors: BTreeMap<_, Vec<_>> = Default::default(); let mut bounds = vec![]; + let mut seen_tys = FxHashSet::default(); + for (field, ty, reason) in fields { + // Only report an error once per type. + if !seen_tys.insert(ty) { + continue; + } + let field_span = tcx.def_span(field.did); err.span_label(field_span, "this field does not implement `Copy`"); @@ -227,7 +236,8 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef use rustc_type_ir::sty::TyKind::*; match (source.kind(), target.kind()) { (&Ref(r_a, _, mutbl_a), Ref(r_b, _, mutbl_b)) - if infcx.at(&cause, param_env).eq(r_a, *r_b).is_ok() && mutbl_a == *mutbl_b => {} + if infcx.at(&cause, param_env).eq(DefineOpaqueTypes::No, r_a, *r_b).is_ok() + && mutbl_a == *mutbl_b => {} (&RawPtr(tm_a), &RawPtr(tm_b)) if tm_a.mutbl == tm_b.mutbl => (), (&Adt(def_a, substs_a), &Adt(def_b, substs_b)) if def_a.is_struct() && def_b.is_struct() => @@ -270,7 +280,9 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef } } - if let Ok(ok) = infcx.at(&cause, param_env).eq(ty_a, ty_b) { + if let Ok(ok) = + infcx.at(&cause, param_env).eq(DefineOpaqueTypes::No, ty_a, ty_b) + { if ok.obligations.is_empty() { create_err( "the trait `DispatchFromDyn` may only be implemented \ @@ -323,28 +335,26 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef )) .emit(); } else { - let errors = traits::fully_solve_obligations( - &infcx, - coerced_fields.into_iter().map(|field| { - predicate_for_trait_def( - tcx, - param_env, - cause.clone(), + let ocx = ObligationCtxt::new(&infcx); + for field in coerced_fields { + ocx.register_obligation(Obligation::new( + tcx, + cause.clone(), + param_env, + ty::Binder::dummy(tcx.mk_trait_ref( dispatch_from_dyn_trait, - 0, [field.ty(tcx, substs_a), field.ty(tcx, substs_b)], - ) - }), - ); + )), + )); + } + let errors = ocx.select_all_or_error(); if !errors.is_empty() { - infcx.err_ctxt().report_fulfillment_errors(&errors, None); + infcx.err_ctxt().report_fulfillment_errors(&errors); } // Finally, resolve all regions. let outlives_env = OutlivesEnvironment::new(param_env); - let _ = infcx - .err_ctxt() - .check_region_obligations_and_report_errors(impl_did, &outlives_env); + let _ = ocx.resolve_regions_and_report_errors(impl_did, &outlives_env); } } _ => { @@ -357,11 +367,8 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef } } -pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedInfo { +pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> CoerceUnsizedInfo { debug!("compute_coerce_unsized_info(impl_did={:?})", impl_did); - - // this provider should only get invoked for local def-ids - let impl_did = impl_did.expect_local(); let span = tcx.def_span(impl_did); let coerce_unsized_trait = tcx.require_lang_item(LangItem::CoerceUnsized, Some(span)); @@ -477,8 +484,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn // U` can be coerced to `*mut V` if `U: Unsize<V>`. let fields = &def_a.non_enum_variant().fields; let diff_fields = fields - .iter() - .enumerate() + .iter_enumerated() .filter_map(|(i, f)| { let (a, b) = (f.ty(tcx, substs_a), f.ty(tcx, substs_b)); @@ -496,7 +502,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn // we may have to evaluate constraint // expressions in the course of execution.) // See e.g., #41936. - if let Ok(ok) = infcx.at(&cause, param_env).eq(a, b) { + if let Ok(ok) = infcx.at(&cause, param_env).eq(DefineOpaqueTypes::No, a, b) { if ok.obligations.is_empty() { return None; } @@ -572,17 +578,19 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn }; // Register an obligation for `A: Trait<B>`. + let ocx = ObligationCtxt::new(&infcx); let cause = traits::ObligationCause::misc(span, impl_did); - let predicate = - predicate_for_trait_def(tcx, param_env, cause, trait_def_id, 0, [source, target]); - let errors = traits::fully_solve_obligation(&infcx, predicate); + let obligation = + Obligation::new(tcx, cause, param_env, tcx.mk_trait_ref(trait_def_id, [source, target])); + ocx.register_obligation(obligation); + let errors = ocx.select_all_or_error(); if !errors.is_empty() { - infcx.err_ctxt().report_fulfillment_errors(&errors, None); + infcx.err_ctxt().report_fulfillment_errors(&errors); } // Finally, resolve all regions. let outlives_env = OutlivesEnvironment::new(param_env); - let _ = infcx.err_ctxt().check_region_obligations_and_report_errors(impl_did, &outlives_env); + let _ = ocx.resolve_regions_and_report_errors(impl_did, &outlives_env); CoerceUnsizedInfo { custom_kind: kind } } diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs index 02f3eeee0..3d37e0ce0 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs @@ -10,7 +10,7 @@ use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::DefKind; -use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::ty::fast_reject::{simplify_type, SimplifiedType, TreatParams}; use rustc_middle::ty::{self, CrateInherentImpls, Ty, TyCtxt}; use rustc_span::symbol::sym; @@ -24,7 +24,7 @@ pub fn crate_inherent_impls(tcx: TyCtxt<'_>, (): ()) -> CrateInherentImpls { collect.impls_map } -pub fn crate_incoherent_impls(tcx: TyCtxt<'_>, (_, simp): (CrateNum, SimplifiedType)) -> &[DefId] { +pub fn crate_incoherent_impls(tcx: TyCtxt<'_>, simp: SimplifiedType) -> &[DefId] { let crate_map = tcx.crate_inherent_impls(()); tcx.arena.alloc_from_iter( crate_map.incoherent_impls.get(&simp).unwrap_or(&Vec::new()).iter().map(|d| d.to_def_id()), @@ -32,9 +32,7 @@ pub fn crate_incoherent_impls(tcx: TyCtxt<'_>, (_, simp): (CrateNum, SimplifiedT } /// On-demand query: yields a vector of the inherent impls for a specific type. -pub fn inherent_impls(tcx: TyCtxt<'_>, ty_def_id: DefId) -> &[DefId] { - let ty_def_id = ty_def_id.expect_local(); - +pub fn inherent_impls(tcx: TyCtxt<'_>, ty_def_id: LocalDefId) -> &[DefId] { let crate_map = tcx.crate_inherent_impls(()); match crate_map.inherent_impls.get(&ty_def_id) { Some(v) => &v[..], @@ -99,7 +97,7 @@ impl<'tcx> InherentCollect<'tcx> { } } - if let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsInfer) { + if let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsCandidateKey) { self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id); } else { bug!("unexpected self type: {:?}", self_ty); @@ -159,7 +157,7 @@ impl<'tcx> InherentCollect<'tcx> { } } - if let Some(simp) = simplify_type(self.tcx, ty, TreatParams::AsInfer) { + if let Some(simp) = simplify_type(self.tcx, ty, TreatParams::AsCandidateKey) { self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id); } else { bug!("unexpected primitive type: {:?}", ty); diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs index 7bca4edcc..ad76e2bed 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs @@ -302,7 +302,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> { .iter() .flatten() .map(|r| r.impl_blocks.len() as isize - avg as isize) - .map(|v| v.abs() as usize) + .map(|v| v.unsigned_abs()) .sum::<usize>(); s / connected_regions.len() }, diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index 23490bc09..465e787c9 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -133,8 +133,8 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) { check_impl(tcx, impl_def_id, trait_ref); check_object_overlap(tcx, impl_def_id, trait_ref); - tcx.sess.time("unsafety_checking", || unsafety::check_item(tcx, impl_def_id)); - tcx.sess.time("orphan_checking", || tcx.ensure().orphan_check_impl(impl_def_id)); + unsafety::check_item(tcx, impl_def_id); + tcx.ensure().orphan_check_impl(impl_def_id); } builtin::check_trait(tcx, def_id); diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index 1f2de3f21..47c47de8c 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -478,10 +478,6 @@ fn lint_auto_trait_impl<'tcx>( trait_ref: ty::TraitRef<'tcx>, impl_def_id: LocalDefId, ) { - if tcx.impl_polarity(impl_def_id) != ImplPolarity::Positive { - return; - } - assert_eq!(trait_ref.substs.len(), 1); let self_ty = trait_ref.self_ty(); let (self_type_did, substs) = match self_ty.kind() { diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 604d54caf..cbbaf8f85 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -20,7 +20,7 @@ use crate::errors; use hir::def::DefKind; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, StashKey}; +use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, StashKey}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{self, Visitor}; @@ -64,6 +64,7 @@ pub fn provide(providers: &mut Providers) { predicates_defined_on, explicit_predicates_of: predicates_of::explicit_predicates_of, super_predicates_of: predicates_of::super_predicates_of, + implied_predicates_of: predicates_of::implied_predicates_of, super_predicates_that_define_assoc_type: predicates_of::super_predicates_that_define_assoc_type, trait_explicit_predicates_and_bounds: predicates_of::trait_explicit_predicates_and_bounds, @@ -113,7 +114,7 @@ pub fn provide(providers: &mut Providers) { /// the AST (`hir::Generics`), recursively. pub struct ItemCtxt<'tcx> { tcx: TyCtxt<'tcx>, - item_def_id: DefId, + item_def_id: LocalDefId, } /////////////////////////////////////////////////////////////////////////// @@ -333,21 +334,11 @@ fn bad_placeholder<'tcx>( let kind = if kind.ends_with('s') { format!("{}es", kind) } else { format!("{}s", kind) }; spans.sort(); - let mut err = struct_span_err!( - tcx.sess, - spans.clone(), - E0121, - "the placeholder `_` is not allowed within types on item signatures for {}", - kind - ); - for span in spans { - err.span_label(span, "not allowed in type signatures"); - } - err + tcx.sess.create_err(errors::PlaceholderNotAllowedItemSignatures { spans, kind }) } impl<'tcx> ItemCtxt<'tcx> { - pub fn new(tcx: TyCtxt<'tcx>, item_def_id: DefId) -> ItemCtxt<'tcx> { + pub fn new(tcx: TyCtxt<'tcx>, item_def_id: LocalDefId) -> ItemCtxt<'tcx> { ItemCtxt { tcx, item_def_id } } @@ -356,7 +347,7 @@ impl<'tcx> ItemCtxt<'tcx> { } pub fn hir_id(&self) -> hir::HirId { - self.tcx.hir().local_def_id_to_hir_id(self.item_def_id.expect_local()) + self.tcx.hir().local_def_id_to_hir_id(self.item_def_id) } pub fn node(&self) -> hir::Node<'tcx> { @@ -370,20 +361,16 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> { } fn item_def_id(&self) -> DefId { - self.item_def_id + self.item_def_id.to_def_id() } fn get_type_parameter_bounds( &self, span: Span, - def_id: DefId, + def_id: LocalDefId, assoc_name: Ident, ) -> ty::GenericPredicates<'tcx> { - self.tcx.at(span).type_param_predicates(( - self.item_def_id, - def_id.expect_local(), - assoc_name, - )) + self.tcx.at(span).type_param_predicates((self.item_def_id, def_id, assoc_name)) } fn re_infer(&self, _: Option<&ty::GenericParamDef>, _: Span) -> Option<ty::Region<'tcx>> { @@ -423,13 +410,8 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> { self.tcx().mk_projection(item_def_id, item_substs) } else { // There are no late-bound regions; we can just ignore the binder. - let mut err = struct_span_err!( - self.tcx().sess, - span, - E0212, - "cannot use the associated type of a trait \ - with uninferred generic parameters" - ); + let (mut mpart_sugg, mut inferred_sugg) = (None, None); + let mut bound = String::new(); match self.node() { hir::Node::Field(_) | hir::Node::Ctor(_) | hir::Node::Variant(_) => { @@ -448,31 +430,25 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> { (bound.span.shrink_to_lo(), format!("{}, ", lt_name)) } }; - let suggestions = vec![ - (lt_sp, sugg), - ( - span.with_hi(item_segment.ident.span.lo()), - format!( - "{}::", - // Replace the existing lifetimes with a new named lifetime. - self.tcx.replace_late_bound_regions_uncached( - poly_trait_ref, - |_| { - self.tcx.mk_re_early_bound(ty::EarlyBoundRegion { - def_id: item_def_id, - index: 0, - name: Symbol::intern(<_name), - }) - } - ), + mpart_sugg = Some(errors::AssociatedTypeTraitUninferredGenericParamsMultipartSuggestion { + fspan: lt_sp, + first: sugg, + sspan: span.with_hi(item_segment.ident.span.lo()), + second: format!( + "{}::", + // Replace the existing lifetimes with a new named lifetime. + self.tcx.replace_late_bound_regions_uncached( + poly_trait_ref, + |_| { + self.tcx.mk_re_early_bound(ty::EarlyBoundRegion { + def_id: item_def_id, + index: 0, + name: Symbol::intern(<_name), + }) + } ), ), - ]; - err.multipart_suggestion( - "use a fully qualified path with explicit lifetimes", - suggestions, - Applicability::MaybeIncorrect, - ); + }); } _ => {} } @@ -486,20 +462,23 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> { | hir::Node::ForeignItem(_) | hir::Node::TraitItem(_) | hir::Node::ImplItem(_) => { - err.span_suggestion_verbose( - span.with_hi(item_segment.ident.span.lo()), - "use a fully qualified path with inferred lifetimes", - format!( - "{}::", - // Erase named lt, we want `<A as B<'_>::C`, not `<A as B<'a>::C`. - self.tcx.anonymize_bound_vars(poly_trait_ref).skip_binder(), - ), - Applicability::MaybeIncorrect, + inferred_sugg = Some(span.with_hi(item_segment.ident.span.lo())); + bound = format!( + "{}::", + // Erase named lt, we want `<A as B<'_>::C`, not `<A as B<'a>::C`. + self.tcx.anonymize_bound_vars(poly_trait_ref).skip_binder(), ); } _ => {} } - self.tcx().ty_error(err.emit()) + self.tcx().ty_error(self.tcx().sess.emit_err( + errors::AssociatedTypeTraitUninferredGenericParams { + span, + inferred_sugg, + bound, + mpart_sugg, + }, + )) } } @@ -618,6 +597,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { } hir::ItemKind::TraitAlias(..) => { tcx.ensure().generics_of(def_id); + tcx.at(it.span).implied_predicates_of(def_id); tcx.at(it.span).super_predicates_of(def_id); tcx.ensure().predicates_of(def_id); } @@ -767,14 +747,12 @@ fn convert_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) { Some(discr) } else { let span = tcx.def_span(variant.def_id); - struct_span_err!(tcx.sess, span, E0370, "enum discriminant overflowed") - .span_label(span, format!("overflowed on value after {}", prev_discr.unwrap())) - .note(&format!( - "explicitly set `{} = {}` if that is desired outcome", - tcx.item_name(variant.def_id), - wrapped_discr - )) - .emit(); + tcx.sess.emit_err(errors::EnumDiscriminantOverflowed { + span, + discr: prev_discr.unwrap().to_string(), + item_name: tcx.item_name(variant.def_id), + wrapped_discr: wrapped_discr.to_string(), + }); None } .unwrap_or(wrapped_discr), @@ -839,17 +817,15 @@ fn convert_variant( adt_kind, parent_did.to_def_id(), recovered, - adt_kind == AdtKind::Struct && tcx.has_attr(parent_did.to_def_id(), sym::non_exhaustive) - || variant_did.map_or(false, |variant_did| { - tcx.has_attr(variant_did.to_def_id(), sym::non_exhaustive) - }), + adt_kind == AdtKind::Struct && tcx.has_attr(parent_did, sym::non_exhaustive) + || variant_did + .map_or(false, |variant_did| tcx.has_attr(variant_did, sym::non_exhaustive)), ) } -fn adt_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AdtDef<'_> { +fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> { use rustc_hir::*; - let def_id = def_id.expect_local(); let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); let Node::Item(item) = tcx.hir().get(hir_id) else { bug!(); @@ -908,8 +884,8 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AdtDef<'_> { tcx.mk_adt_def(def_id.to_def_id(), kind, variants, repr) } -fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef { - let item = tcx.hir().expect_item(def_id.expect_local()); +fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef { + let item = tcx.hir().expect_item(def_id); let (is_auto, unsafety, items) = match item.kind { hir::ItemKind::Trait(is_auto, unsafety, .., items) => { @@ -921,14 +897,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef { let paren_sugar = tcx.has_attr(def_id, sym::rustc_paren_sugar); if paren_sugar && !tcx.features().unboxed_closures { - tcx.sess - .struct_span_err( - item.span, - "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") - .emit(); + tcx.sess.emit_err(errors::ParenSugarAttribute { span: item.span }); } let is_marker = tcx.has_attr(def_id, sym::marker); @@ -948,13 +917,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef { // and that they are all identifiers .and_then(|attr| match attr.meta_item_list() { Some(items) if items.len() < 2 => { - tcx.sess - .struct_span_err( - attr.span, - "the `#[rustc_must_implement_one_of]` attribute must be \ - used with at least 2 args", - ) - .emit(); + tcx.sess.emit_err(errors::MustImplementOneOfAttribute { span: attr.span }); None } @@ -963,9 +926,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef { .map(|item| item.ident().ok_or(item.span())) .collect::<Result<Box<[_]>, _>>() .map_err(|span| { - tcx.sess - .struct_span_err(span, "must be a name of an associated function") - .emit(); + tcx.sess.emit_err(errors::MustBeNameOfAssociatedFunction { span }); }) .ok() .zip(Some(attr.span)), @@ -981,13 +942,10 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef { match item { Some(item) if matches!(item.kind, hir::AssocItemKind::Fn { .. }) => { if !tcx.impl_defaultness(item.id.owner_id).has_value() { - tcx.sess - .struct_span_err( - item.span, - "function doesn't have a default implementation", - ) - .span_note(attr_span, "required by this annotation") - .emit(); + tcx.sess.emit_err(errors::FunctionNotHaveDefaultImplementation { + span: item.span, + note_span: attr_span, + }); return Some(()); } @@ -995,19 +953,14 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef { return None; } Some(item) => { - tcx.sess - .struct_span_err(item.span, "not a function") - .span_note(attr_span, "required by this annotation") - .note( - "all `#[rustc_must_implement_one_of]` arguments must be associated \ - function names", - ) - .emit(); + tcx.sess.emit_err(errors::MustImplementNotFunction { + span: item.span, + span_note: errors::MustImplementNotFunctionSpanNote { span: attr_span }, + note: errors::MustImplementNotFunctionNote {}, + }); } None => { - tcx.sess - .struct_span_err(ident.span, "function not found in this trait") - .emit(); + tcx.sess.emit_err(errors::FunctionNotFoundInTrait { span: ident.span }); } } @@ -1024,9 +977,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef { for ident in &*list { if let Some(dup) = set.insert(ident.name, ident.span) { tcx.sess - .struct_span_err(vec![dup, ident.span], "functions names are duplicated") - .note("all `#[rustc_must_implement_one_of]` arguments must be unique") - .emit(); + .emit_err(errors::FunctionNamesDuplicated { spans: vec![dup, ident.span] }); no_dups = false; } @@ -1036,7 +987,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef { }); ty::TraitDef { - def_id, + def_id: def_id.to_def_id(), unsafety, paren_sugar, has_auto_impl: is_auto, @@ -1091,14 +1042,13 @@ pub fn get_infer_ret_ty<'hir>(output: &'hir hir::FnRetTy<'hir>) -> Option<&'hir } #[instrument(level = "debug", skip(tcx))] -fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<ty::PolyFnSig<'_>> { +fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<ty::PolyFnSig<'_>> { use rustc_hir::Node::*; use rustc_hir::*; - let def_id = def_id.expect_local(); let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let icx = ItemCtxt::new(tcx, def_id.to_def_id()); + let icx = ItemCtxt::new(tcx, def_id); let output = match tcx.hir().get(hir_id) { TraitItem(hir::TraitItem { @@ -1139,7 +1089,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<ty::PolyFnSig<'_>> ForeignItem(&hir::ForeignItem { kind: ForeignItemKind::Fn(fn_decl, _, _), .. }) => { let abi = tcx.hir().get_foreign_abi(hir_id); - compute_sig_of_foreign_fn_decl(tcx, def_id.to_def_id(), fn_decl, abi) + compute_sig_of_foreign_fn_decl(tcx, def_id, fn_decl, abi) } Ctor(data) | Variant(hir::Variant { data, .. }) if data.ctor().is_some() => { @@ -1215,7 +1165,7 @@ fn infer_return_ty_for_fn_sig<'tcx>( fn_sig, Applicability::MachineApplicable, ); - } else if let Some(sugg) = suggest_impl_trait(tcx, ret_ty, ty.span, hir_id, def_id) { + } else if let Some(sugg) = suggest_impl_trait(tcx, ret_ty, ty.span, def_id) { diag.span_suggestion( ty.span, "replace with an appropriate return type", @@ -1247,12 +1197,10 @@ fn infer_return_ty_for_fn_sig<'tcx>( } } -// FIXME(vincenzopalazzo): remove the hir item when the refactoring is stable fn suggest_impl_trait<'tcx>( tcx: TyCtxt<'tcx>, ret_ty: Ty<'tcx>, span: Span, - _hir_id: hir::HirId, def_id: LocalDefId, ) -> Option<String> { let format_as_assoc: fn(_, _, _, _, _) -> _ = @@ -1338,9 +1286,12 @@ fn suggest_impl_trait<'tcx>( None } -fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::EarlyBinder<ty::TraitRef<'_>>> { +fn impl_trait_ref( + tcx: TyCtxt<'_>, + def_id: LocalDefId, +) -> Option<ty::EarlyBinder<ty::TraitRef<'_>>> { let icx = ItemCtxt::new(tcx, def_id); - let impl_ = tcx.hir().expect_item(def_id.expect_local()).expect_impl(); + let impl_ = tcx.hir().expect_item(def_id).expect_impl(); impl_ .of_trait .as_ref() @@ -1380,9 +1331,9 @@ fn check_impl_constness( } } -fn impl_polarity(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ImplPolarity { +fn impl_polarity(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::ImplPolarity { let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl); - let item = tcx.hir().expect_item(def_id.expect_local()); + let item = tcx.hir().expect_item(def_id); match &item.kind { hir::ItemKind::Impl(hir::Impl { polarity: hir::ImplPolarity::Negative(span), @@ -1465,16 +1416,16 @@ fn predicates_defined_on(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicate fn compute_sig_of_foreign_fn_decl<'tcx>( tcx: TyCtxt<'tcx>, - def_id: DefId, + def_id: LocalDefId, decl: &'tcx hir::FnDecl<'tcx>, abi: abi::Abi, ) -> ty::PolyFnSig<'tcx> { let unsafety = if abi == abi::Abi::RustIntrinsic { - intrinsic_operation_unsafety(tcx, def_id) + intrinsic_operation_unsafety(tcx, def_id.to_def_id()) } else { hir::Unsafety::Unsafe }; - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); let fty = ItemCtxt::new(tcx, def_id).astconv().ty_of_fn(hir_id, unsafety, abi, decl, None, None); @@ -1491,17 +1442,7 @@ fn compute_sig_of_foreign_fn_decl<'tcx>( .source_map() .span_to_snippet(ast_ty.span) .map_or_else(|_| String::new(), |s| format!(" `{}`", s)); - tcx.sess - .struct_span_err( - ast_ty.span, - &format!( - "use of SIMD type{} in FFI is highly experimental and \ - may result in invalid code", - snip - ), - ) - .help("add `#![feature(simd_ffi)]` to the crate attributes to enable") - .emit(); + tcx.sess.emit_err(errors::SIMDFFIHighlyExperimental { span: ast_ty.span, snip }); } }; for (input, ty) in iter::zip(decl.inputs, fty.inputs().skip_binder()) { @@ -1515,31 +1456,28 @@ fn compute_sig_of_foreign_fn_decl<'tcx>( fty } -fn is_foreign_item(tcx: TyCtxt<'_>, def_id: DefId) -> bool { - match tcx.hir().get_if_local(def_id) { - Some(Node::ForeignItem(..)) => true, - Some(_) => false, - _ => bug!("is_foreign_item applied to non-local def-id {:?}", def_id), +fn is_foreign_item(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { + match tcx.hir().get_by_def_id(def_id) { + Node::ForeignItem(..) => true, + _ => false, } } -fn generator_kind(tcx: TyCtxt<'_>, def_id: DefId) -> Option<hir::GeneratorKind> { - match tcx.hir().get_if_local(def_id) { - Some(Node::Expr(&rustc_hir::Expr { +fn generator_kind(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<hir::GeneratorKind> { + match tcx.hir().get_by_def_id(def_id) { + Node::Expr(&rustc_hir::Expr { kind: rustc_hir::ExprKind::Closure(&rustc_hir::Closure { body, .. }), .. - })) => tcx.hir().body(body).generator_kind(), - Some(_) => None, - _ => bug!("generator_kind applied to non-local def-id {:?}", def_id), + }) => tcx.hir().body(body).generator_kind(), + _ => None, } } -fn is_type_alias_impl_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool { - match tcx.hir().get_if_local(def_id) { - Some(Node::Item(hir::Item { kind: hir::ItemKind::OpaqueTy(opaque), .. })) => { +fn is_type_alias_impl_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool { + match tcx.hir().get_by_def_id(def_id) { + Node::Item(hir::Item { kind: hir::ItemKind::OpaqueTy(opaque), .. }) => { matches!(opaque.origin, hir::OpaqueTyOrigin::TyAlias) } - Some(_) => bug!("tried getting opaque_ty_origin for non-opaque: {:?}", def_id), - _ => bug!("tried getting opaque_ty_origin for non-local def-id {:?}", def_id), + _ => bug!("tried getting opaque_ty_origin for non-opaque: {:?}", def_id), } } diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 127d4fa90..119933697 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -5,16 +5,16 @@ use hir::{ }; use rustc_hir as hir; use rustc_hir::def::DefKind; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::LocalDefId; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::lint; use rustc_span::symbol::{kw, Symbol}; use rustc_span::Span; -pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { +pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { use rustc_hir::*; - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); let node = tcx.hir().get(hir_id); let parent_def_id = match node { @@ -121,7 +121,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { Some(parent_def_id.to_def_id()) } Node::Expr(&Expr { kind: ExprKind::ConstBlock(_), .. }) => { - Some(tcx.typeck_root_def_id(def_id)) + Some(tcx.typeck_root_def_id(def_id.to_def_id())) } // Exclude `GlobalAsm` here which cannot have generics. Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. }) @@ -140,7 +140,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { } } Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => { - Some(tcx.typeck_root_def_id(def_id)) + Some(tcx.typeck_root_def_id(def_id.to_def_id())) } Node::Item(item) => match item.kind { ItemKind::OpaqueTy(hir::OpaqueTy { @@ -189,7 +189,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { let opt_self = Some(ty::GenericParamDef { index: 0, name: kw::SelfUpper, - def_id, + def_id: def_id.to_def_id(), pure_wrt_drop: false, kind: ty::GenericParamDefKind::Type { has_default: false, @@ -326,7 +326,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { params.extend(dummy_args.iter().map(|&arg| ty::GenericParamDef { index: next_index(), name: Symbol::intern(arg), - def_id, + def_id: def_id.to_def_id(), pure_wrt_drop: false, kind: ty::GenericParamDefKind::Type { has_default: false, synthetic: false }, })); @@ -339,7 +339,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { params.push(ty::GenericParamDef { index: next_index(), name: Symbol::intern("<const_ty>"), - def_id, + def_id: def_id.to_def_id(), pure_wrt_drop: false, kind: ty::GenericParamDefKind::Type { has_default: false, synthetic: false }, }); diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index 9cf3ff65a..2e56d2463 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -3,8 +3,8 @@ use crate::astconv::AstConv; use rustc_hir as hir; use rustc_infer::traits::util; use rustc_middle::ty::subst::InternalSubsts; -use rustc_middle::ty::{self, DefIdTree, TyCtxt}; -use rustc_span::def_id::DefId; +use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::Span; /// For associated types we include both bounds written on the type @@ -16,12 +16,12 @@ use rustc_span::Span; /// `hr-associated-type-bound-1.rs`. fn associated_type_bounds<'tcx>( tcx: TyCtxt<'tcx>, - assoc_item_def_id: DefId, + assoc_item_def_id: LocalDefId, ast_bounds: &'tcx [hir::GenericBound<'tcx>], span: Span, ) -> &'tcx [(ty::Predicate<'tcx>, Span)] { let item_ty = tcx.mk_projection( - assoc_item_def_id, + assoc_item_def_id.to_def_id(), InternalSubsts::identity_for_item(tcx, assoc_item_def_id), ); @@ -30,8 +30,8 @@ fn associated_type_bounds<'tcx>( // Associated types are implicitly sized unless a `?Sized` bound is found icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span); - let trait_def_id = tcx.parent(assoc_item_def_id); - let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id.expect_local()); + let trait_def_id = tcx.local_parent(assoc_item_def_id); + let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id); let bounds_from_parent = trait_predicates.predicates.iter().copied().filter(|(pred, _)| { match pred.kind().skip_binder() { @@ -45,7 +45,11 @@ fn associated_type_bounds<'tcx>( }); let all_bounds = tcx.arena.alloc_from_iter(bounds.predicates().chain(bounds_from_parent)); - debug!("associated_type_bounds({}) = {:?}", tcx.def_path_str(assoc_item_def_id), all_bounds); + debug!( + "associated_type_bounds({}) = {:?}", + tcx.def_path_str(assoc_item_def_id.to_def_id()), + all_bounds + ); all_bounds } @@ -56,19 +60,12 @@ fn associated_type_bounds<'tcx>( #[instrument(level = "trace", skip(tcx), ret)] fn opaque_type_bounds<'tcx>( tcx: TyCtxt<'tcx>, - opaque_def_id: DefId, + opaque_def_id: LocalDefId, ast_bounds: &'tcx [hir::GenericBound<'tcx>], + item_ty: Ty<'tcx>, span: Span, - in_trait: bool, ) -> &'tcx [(ty::Predicate<'tcx>, Span)] { ty::print::with_no_queries!({ - let substs = InternalSubsts::identity_for_item(tcx, opaque_def_id); - let item_ty = if in_trait { - tcx.mk_projection(opaque_def_id, substs) - } else { - tcx.mk_opaque(opaque_def_id, substs) - }; - let icx = ItemCtxt::new(tcx, opaque_def_id); let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds); // Opaque types are implicitly sized unless a `?Sized` bound is found @@ -81,9 +78,31 @@ fn opaque_type_bounds<'tcx>( pub(super) fn explicit_item_bounds( tcx: TyCtxt<'_>, - def_id: DefId, + def_id: LocalDefId, ) -> &'_ [(ty::Predicate<'_>, Span)] { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); + match tcx.opt_rpitit_info(def_id.to_def_id()) { + // RPITIT's bounds are the same as opaque type bounds, but with + // a projection self type. + Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => { + let item = tcx.hir().get_by_def_id(opaque_def_id.expect_local()).expect_item(); + let opaque_ty = item.expect_opaque_ty(); + return opaque_type_bounds( + tcx, + opaque_def_id.expect_local(), + opaque_ty.bounds, + tcx.mk_projection( + def_id.to_def_id(), + ty::InternalSubsts::identity_for_item(tcx, def_id), + ), + item.span, + ); + } + // These should have been fed! + Some(ty::ImplTraitInTraitData::Impl { .. }) => unreachable!(), + None => {} + } + + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); match tcx.hir().get(hir_id) { hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Type(bounds, _), @@ -94,7 +113,15 @@ pub(super) fn explicit_item_bounds( kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, in_trait, .. }), span, .. - }) => opaque_type_bounds(tcx, def_id, bounds, *span, *in_trait), + }) => { + let substs = InternalSubsts::identity_for_item(tcx, def_id); + let item_ty = if *in_trait && !tcx.lower_impl_trait_in_trait_to_assoc_ty() { + tcx.mk_projection(def_id.to_def_id(), substs) + } else { + tcx.mk_opaque(def_id.to_def_id(), substs) + }; + opaque_type_bounds(tcx, def_id, bounds, item_ty, *span) + } _ => bug!("item_bounds called on {:?}", def_id), } } @@ -103,12 +130,9 @@ pub(super) fn item_bounds( tcx: TyCtxt<'_>, def_id: DefId, ) -> ty::EarlyBinder<&'_ ty::List<ty::Predicate<'_>>> { - let bounds = tcx.mk_predicates_from_iter( - util::elaborate_predicates( - tcx, - tcx.explicit_item_bounds(def_id).iter().map(|&(bound, _span)| bound), - ) - .map(|obligation| obligation.predicate), - ); + let bounds = tcx.mk_predicates_from_iter(util::elaborate( + tcx, + tcx.explicit_item_bounds(def_id).iter().map(|&(bound, _span)| bound), + )); ty::EarlyBinder(bounds) } diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 2badd66e3..9358ed612 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -62,15 +62,16 @@ pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredic /// Returns a list of user-specified type predicates for the definition with ID `def_id`. /// N.B., this does not include any implied/inferred constraints. #[instrument(level = "trace", skip(tcx), ret)] -fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> { +fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::GenericPredicates<'_> { use rustc_hir::*; - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); let node = tcx.hir().get(hir_id); let mut is_trait = None; let mut is_default_impl_trait = None; + // FIXME: Should ItemCtxt take a LocalDefId? let icx = ItemCtxt::new(tcx, def_id); const NO_GENERICS: &hir::Generics<'_> = hir::Generics::empty(); @@ -99,7 +100,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP | ItemKind::Union(_, generics) => generics, ItemKind::Trait(_, _, generics, ..) | ItemKind::TraitAlias(generics, _) => { - is_trait = Some(ty::TraitRef::identity(tcx, def_id)); + is_trait = Some(ty::TraitRef::identity(tcx, def_id.to_def_id())); generics } ItemKind::OpaqueTy(OpaqueTy { generics, .. }) => generics, @@ -124,7 +125,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP // on a trait we need to add in the supertrait bounds and bounds found on // associated types. if let Some(_trait_ref) = is_trait { - predicates.extend(tcx.super_predicates_of(def_id).predicates.iter().cloned()); + predicates.extend(tcx.implied_predicates_of(def_id).predicates.iter().cloned()); } // In default impls, we can assume that the self type implements @@ -253,7 +254,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP } if tcx.features().generic_const_exprs { - predicates.extend(const_evaluatable_predicates_of(tcx, def_id.expect_local())); + predicates.extend(const_evaluatable_predicates_of(tcx, def_id)); } let mut predicates: Vec<_> = predicates.into_iter().collect(); @@ -392,18 +393,18 @@ pub(super) fn trait_explicit_predicates_and_bounds( def_id: LocalDefId, ) -> ty::GenericPredicates<'_> { assert_eq!(tcx.def_kind(def_id), DefKind::Trait); - gather_explicit_predicates_of(tcx, def_id.to_def_id()) + gather_explicit_predicates_of(tcx, def_id) } pub(super) fn explicit_predicates_of<'tcx>( tcx: TyCtxt<'tcx>, - def_id: DefId, + def_id: LocalDefId, ) -> ty::GenericPredicates<'tcx> { let def_kind = tcx.def_kind(def_id); if let DefKind::Trait = def_kind { // Remove bounds on associated types from the predicates, they will be // returned by `explicit_item_bounds`. - let predicates_and_bounds = tcx.trait_explicit_predicates_and_bounds(def_id.expect_local()); + let predicates_and_bounds = tcx.trait_explicit_predicates_and_bounds(def_id); let trait_identity_substs = InternalSubsts::identity_for_item(tcx, def_id); let is_assoc_item_ty = |ty: Ty<'tcx>| { @@ -418,7 +419,8 @@ pub(super) fn explicit_predicates_of<'tcx>( // supertrait). if let ty::Alias(ty::Projection, projection) = ty.kind() { projection.substs == trait_identity_substs - && tcx.associated_item(projection.def_id).container_id(tcx) == def_id + && tcx.associated_item(projection.def_id).container_id(tcx) + == def_id.to_def_id() } else { false } @@ -449,7 +451,7 @@ pub(super) fn explicit_predicates_of<'tcx>( } } else { if matches!(def_kind, DefKind::AnonConst) && tcx.lazy_normalization() { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); let parent_def_id = tcx.hir().get_parent_item(hir_id); if let Some(defaulted_param_def_id) = @@ -532,89 +534,136 @@ pub(super) fn explicit_predicates_of<'tcx>( } } +#[derive(Copy, Clone, Debug)] +pub enum PredicateFilter { + /// All predicates may be implied by the trait + All, + + /// Only traits that reference `Self: ..` are implied by the trait + SelfOnly, + + /// Only traits that reference `Self: ..` and define an associated type + /// with the given ident are implied by the trait + SelfThatDefines(Ident), +} + /// Ensures that the super-predicates of the trait with a `DefId` /// of `trait_def_id` are converted and stored. This also ensures that /// the transitive super-predicates are converted. pub(super) fn super_predicates_of( tcx: TyCtxt<'_>, - trait_def_id: DefId, + trait_def_id: LocalDefId, +) -> ty::GenericPredicates<'_> { + implied_predicates_with_filter(tcx, trait_def_id.to_def_id(), PredicateFilter::SelfOnly) +} + +pub(super) fn super_predicates_that_define_assoc_type( + tcx: TyCtxt<'_>, + (trait_def_id, assoc_name): (DefId, Ident), +) -> ty::GenericPredicates<'_> { + implied_predicates_with_filter(tcx, trait_def_id, PredicateFilter::SelfThatDefines(assoc_name)) +} + +pub(super) fn implied_predicates_of( + tcx: TyCtxt<'_>, + trait_def_id: LocalDefId, ) -> ty::GenericPredicates<'_> { - tcx.super_predicates_that_define_assoc_type((trait_def_id, None)) + if tcx.is_trait_alias(trait_def_id.to_def_id()) { + implied_predicates_with_filter(tcx, trait_def_id.to_def_id(), PredicateFilter::All) + } else { + tcx.super_predicates_of(trait_def_id) + } } /// Ensures that the super-predicates of the trait with a `DefId` /// of `trait_def_id` are converted and stored. This also ensures that /// the transitive super-predicates are converted. -pub(super) fn super_predicates_that_define_assoc_type( +pub(super) fn implied_predicates_with_filter( tcx: TyCtxt<'_>, - (trait_def_id, assoc_name): (DefId, Option<Ident>), + trait_def_id: DefId, + filter: PredicateFilter, ) -> ty::GenericPredicates<'_> { - if trait_def_id.is_local() { - debug!("local trait"); - let trait_hir_id = tcx.hir().local_def_id_to_hir_id(trait_def_id.expect_local()); - - let Node::Item(item) = tcx.hir().get(trait_hir_id) else { - bug!("trait_node_id {} is not an item", trait_hir_id); - }; + let Some(trait_def_id) = trait_def_id.as_local() else { + // if `assoc_name` is None, then the query should've been redirected to an + // external provider + assert!(matches!(filter, PredicateFilter::SelfThatDefines(_))); + return tcx.super_predicates_of(trait_def_id); + }; - let (generics, bounds) = match item.kind { - hir::ItemKind::Trait(.., generics, supertraits, _) => (generics, supertraits), - hir::ItemKind::TraitAlias(generics, supertraits) => (generics, supertraits), - _ => span_bug!(item.span, "super_predicates invoked on non-trait"), - }; + let trait_hir_id = tcx.hir().local_def_id_to_hir_id(trait_def_id); - let icx = ItemCtxt::new(tcx, trait_def_id); + let Node::Item(item) = tcx.hir().get(trait_hir_id) else { + bug!("trait_node_id {} is not an item", trait_hir_id); + }; - // Convert the bounds that follow the colon, e.g., `Bar + Zed` in `trait Foo: Bar + Zed`. - let self_param_ty = tcx.types.self_param; - let superbounds1 = if let Some(assoc_name) = assoc_name { - icx.astconv().compute_bounds_that_match_assoc_type(self_param_ty, bounds, assoc_name) - } else { - icx.astconv().compute_bounds(self_param_ty, bounds) - }; + let (generics, bounds) = match item.kind { + hir::ItemKind::Trait(.., generics, supertraits, _) => (generics, supertraits), + hir::ItemKind::TraitAlias(generics, supertraits) => (generics, supertraits), + _ => span_bug!(item.span, "super_predicates invoked on non-trait"), + }; - let superbounds1 = superbounds1.predicates(); - - // Convert any explicit superbounds in the where-clause, - // e.g., `trait Foo where Self: Bar`. - // In the case of trait aliases, however, we include all bounds in the where-clause, - // so e.g., `trait Foo = where u32: PartialEq<Self>` would include `u32: PartialEq<Self>` - // as one of its "superpredicates". - let is_trait_alias = tcx.is_trait_alias(trait_def_id); - let superbounds2 = icx.type_parameter_bounds_in_generics( - generics, - item.owner_id.def_id, - self_param_ty, - OnlySelfBounds(!is_trait_alias), - assoc_name, - ); + let icx = ItemCtxt::new(tcx, trait_def_id); + + let self_param_ty = tcx.types.self_param; + let (superbounds, where_bounds_that_match) = match filter { + PredicateFilter::All => ( + // Convert the bounds that follow the colon (or equal in trait aliases) + icx.astconv().compute_bounds(self_param_ty, bounds), + // Also include all where clause bounds + icx.type_parameter_bounds_in_generics( + generics, + item.owner_id.def_id, + self_param_ty, + OnlySelfBounds(false), + None, + ), + ), + PredicateFilter::SelfOnly => ( + // Convert the bounds that follow the colon (or equal in trait aliases) + icx.astconv().compute_bounds(self_param_ty, bounds), + // Include where clause bounds for `Self` + icx.type_parameter_bounds_in_generics( + generics, + item.owner_id.def_id, + self_param_ty, + OnlySelfBounds(true), + None, + ), + ), + PredicateFilter::SelfThatDefines(assoc_name) => ( + // Convert the bounds that follow the colon (or equal) that reference the associated name + icx.astconv().compute_bounds_that_match_assoc_type(self_param_ty, bounds, assoc_name), + // Include where clause bounds for `Self` that reference the associated name + icx.type_parameter_bounds_in_generics( + generics, + item.owner_id.def_id, + self_param_ty, + OnlySelfBounds(true), + Some(assoc_name), + ), + ), + }; - // Combine the two lists to form the complete set of superbounds: - let superbounds = &*tcx.arena.alloc_from_iter(superbounds1.into_iter().chain(superbounds2)); - debug!(?superbounds); + // Combine the two lists to form the complete set of superbounds: + let implied_bounds = &*tcx + .arena + .alloc_from_iter(superbounds.predicates().into_iter().chain(where_bounds_that_match)); + debug!(?implied_bounds); + // Now require that immediate supertraits are converted, + // which will, in turn, reach indirect supertraits. + if matches!(filter, PredicateFilter::SelfOnly) { // Now require that immediate supertraits are converted, // which will, in turn, reach indirect supertraits. - if assoc_name.is_none() { - // Now require that immediate supertraits are converted, - // which will, in turn, reach indirect supertraits. - for &(pred, span) in superbounds { - debug!("superbound: {:?}", pred); - if let ty::PredicateKind::Clause(ty::Clause::Trait(bound)) = - pred.kind().skip_binder() - { - tcx.at(span).super_predicates_of(bound.def_id()); - } + for &(pred, span) in implied_bounds { + debug!("superbound: {:?}", pred); + if let ty::PredicateKind::Clause(ty::Clause::Trait(bound)) = pred.kind().skip_binder() { + tcx.at(span).super_predicates_of(bound.def_id()); } } - - ty::GenericPredicates { parent: None, predicates: superbounds } - } else { - // if `assoc_name` is None, then the query should've been redirected to an - // external provider - assert!(assoc_name.is_some()); - tcx.super_predicates_of(trait_def_id) } + + ty::GenericPredicates { parent: None, predicates: implied_bounds } } /// Returns the predicates defined on `item_def_id` of the form @@ -622,7 +671,7 @@ pub(super) fn super_predicates_that_define_assoc_type( #[instrument(level = "trace", skip(tcx))] pub(super) fn type_param_predicates( tcx: TyCtxt<'_>, - (item_def_id, def_id, assoc_name): (DefId, LocalDefId, Ident), + (item_def_id, def_id, assoc_name): (LocalDefId, LocalDefId, Ident), ) -> ty::GenericPredicates<'_> { use rustc_hir::*; @@ -637,21 +686,21 @@ pub(super) fn type_param_predicates( let ty = tcx.mk_ty_param(index, tcx.hir().ty_param_name(def_id)); // Don't look for bounds where the type parameter isn't in scope. - let parent = if item_def_id == param_owner.to_def_id() { + let parent = if item_def_id == param_owner { None } else { - tcx.generics_of(item_def_id).parent + tcx.generics_of(item_def_id).parent.map(|def_id| def_id.expect_local()) }; let mut result = parent .map(|parent| { let icx = ItemCtxt::new(tcx, parent); - icx.get_type_parameter_bounds(DUMMY_SP, def_id.to_def_id(), assoc_name) + icx.get_type_parameter_bounds(DUMMY_SP, def_id, assoc_name) }) .unwrap_or_default(); let mut extend = None; - let item_hir_id = tcx.hir().local_def_id_to_hir_id(item_def_id.expect_local()); + let item_hir_id = tcx.hir().local_def_id_to_hir_id(item_def_id); let ast_generics = match tcx.hir().get(item_hir_id) { Node::TraitItem(item) => &item.generics, @@ -673,7 +722,8 @@ pub(super) fn type_param_predicates( ItemKind::Trait(_, _, generics, ..) => { // Implied `Self: Trait` and supertrait bounds. if param_id == item_hir_id { - let identity_trait_ref = ty::TraitRef::identity(tcx, item_def_id); + let identity_trait_ref = + ty::TraitRef::identity(tcx, item_def_id.to_def_id()); extend = Some((identity_trait_ref.without_const().to_predicate(tcx), item.span)); } diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 65a9052a6..e758fe95d 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -17,7 +17,7 @@ use rustc_hir::{GenericArg, GenericParam, GenericParamKind, HirIdMap, LifetimeNa use rustc_middle::bug; use rustc_middle::hir::nested_filter; use rustc_middle::middle::resolve_bound_vars::*; -use rustc_middle::ty::{self, DefIdTree, TyCtxt, TypeSuperVisitable, TypeVisitor}; +use rustc_middle::ty::{self, TyCtxt, TypeSuperVisitable, TypeVisitor}; use rustc_session::lint; use rustc_span::def_id::DefId; use rustc_span::symbol::{sym, Ident}; @@ -1051,9 +1051,8 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { } } -fn object_lifetime_default(tcx: TyCtxt<'_>, param_def_id: DefId) -> ObjectLifetimeDefault { +fn object_lifetime_default(tcx: TyCtxt<'_>, param_def_id: LocalDefId) -> ObjectLifetimeDefault { debug_assert_eq!(tcx.def_kind(param_def_id), DefKind::TyParam); - let param_def_id = param_def_id.expect_local(); let hir::Node::GenericParam(param) = tcx.hir().get_by_def_id(param_def_id) else { bug!("expected GenericParam for object_lifetime_default"); }; @@ -1427,25 +1426,25 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { if let ResolvedArg::LateBound(..) = def && crossed_anon_const { let use_span = self.tcx.hir().span(hir_id); let def_span = self.tcx.def_span(param_def_id); - match self.tcx.def_kind(param_def_id) { + let guar = match self.tcx.def_kind(param_def_id) { DefKind::ConstParam => { self.tcx.sess.emit_err(errors::CannotCaptureLateBoundInAnonConst::Const { use_span, def_span, - }); + }) } DefKind::TyParam => { self.tcx.sess.emit_err(errors::CannotCaptureLateBoundInAnonConst::Type { use_span, def_span, - }); + }) } _ => unreachable!(), - } - return; + }; + self.map.defs.insert(hir_id, ResolvedArg::Error(guar)); + } else { + self.map.defs.insert(hir_id, def); } - - self.map.defs.insert(hir_id, def); return; } @@ -1462,7 +1461,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { depth: usize, generic_args: &'tcx hir::GenericArgs<'tcx>, ) { - if generic_args.parenthesized { + if generic_args.parenthesized == hir::GenericArgsParentheses::ParenSugar { self.visit_fn_like_elision( generic_args.inputs(), Some(generic_args.bindings[0].ty()), @@ -1641,7 +1640,59 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { }, s: self.scope, }; - if let Some(type_def_id) = type_def_id { + // If the binding is parenthesized, then this must be `feature(return_type_notation)`. + // In that case, introduce a binder over all of the function's early and late bound vars. + // + // For example, given + // ``` + // trait Foo { + // async fn x<'r, T>(); + // } + // ``` + // and a bound that looks like: + // `for<'a> T::Trait<'a, x(): for<'b> Other<'b>>` + // this is going to expand to something like: + // `for<'a> for<'r, T> <T as Trait<'a>>::x::<'r, T>::{opaque#0}: for<'b> Other<'b>`. + if binding.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation { + let bound_vars = if let Some(type_def_id) = type_def_id + && self.tcx.def_kind(type_def_id) == DefKind::Trait + // FIXME(return_type_notation): We could bound supertrait methods. + && let Some(assoc_fn) = self + .tcx + .associated_items(type_def_id) + .find_by_name_and_kind(self.tcx, binding.ident, ty::AssocKind::Fn, type_def_id) + { + self.tcx + .generics_of(assoc_fn.def_id) + .params + .iter() + .map(|param| match param.kind { + ty::GenericParamDefKind::Lifetime => ty::BoundVariableKind::Region( + ty::BoundRegionKind::BrNamed(param.def_id, param.name), + ), + ty::GenericParamDefKind::Type { .. } => ty::BoundVariableKind::Ty( + ty::BoundTyKind::Param(param.def_id, param.name), + ), + ty::GenericParamDefKind::Const { .. } => ty::BoundVariableKind::Const, + }) + .chain(self.tcx.fn_sig(assoc_fn.def_id).subst_identity().bound_vars()) + .collect() + } else { + self.tcx.sess.delay_span_bug( + binding.ident.span, + "bad return type notation here", + ); + vec![] + }; + self.with(scope, |this| { + let scope = Scope::Supertrait { bound_vars, s: this.scope }; + this.with(scope, |this| { + let (bound_vars, _) = this.poly_trait_ref_binder_info(); + this.record_late_bound_vars(binding.hir_id, bound_vars); + this.visit_assoc_type_binding(binding) + }); + }); + } else if let Some(type_def_id) = type_def_id { let bound_vars = BoundVarContext::supertrait_hrtb_vars(self.tcx, type_def_id, binding.ident); self.with(scope, |this| { @@ -1698,8 +1749,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { if trait_defines_associated_type_named(def_id) { break Some(bound_vars.into_iter().collect()); } - let predicates = - tcx.super_predicates_that_define_assoc_type((def_id, Some(assoc_name))); + let predicates = tcx.super_predicates_that_define_assoc_type((def_id, assoc_name)); let obligations = predicates.predicates.iter().filter_map(|&(pred, _)| { let bound_predicate = pred.kind(); match bound_predicate.skip_binder() { diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 50073d94e..c173bd913 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -8,9 +8,7 @@ use rustc_middle::hir::nested_filter; use rustc_middle::ty::print::with_forced_trimmed_paths; use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::util::IntTypeExt; -use rustc_middle::ty::{ - self, DefIdTree, IsSuggestable, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitableExt, -}; +use rustc_middle::ty::{self, ImplTraitInTraitData, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::symbol::Ident; use rustc_span::{Span, DUMMY_SP}; @@ -62,7 +60,7 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option< .find(|(_, node)| matches!(node, OwnerNode::Item(_))) .unwrap() .0 - .to_def_id(); + .def_id; let item_ctxt = &ItemCtxt::new(tcx, item_def_id) as &dyn crate::astconv::AstConv<'_>; let ty = item_ctxt.ast_ty_to_ty(hir_ty); @@ -243,24 +241,46 @@ fn get_path_containing_arg_in_pat<'hir>( arg_path } -pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<Ty<'_>> { - let def_id = def_id.expect_local(); +pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty<'_>> { + // If we are computing `type_of` the synthesized associated type for an RPITIT in the impl + // side, use `collect_return_position_impl_trait_in_trait_tys` to infer the value of the + // associated type in the impl. + if let Some(ImplTraitInTraitData::Impl { fn_def_id, .. }) = + tcx.opt_rpitit_info(def_id.to_def_id()) + { + match tcx.collect_return_position_impl_trait_in_trait_tys(fn_def_id) { + Ok(map) => { + let assoc_item = tcx.associated_item(def_id); + return ty::EarlyBinder(map[&assoc_item.trait_item_def_id.unwrap()]); + } + Err(_) => { + return ty::EarlyBinder(tcx.ty_error_with_message( + DUMMY_SP, + "Could not collect return position impl trait in trait tys", + )); + } + } + } + use rustc_hir::*; let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let icx = ItemCtxt::new(tcx, def_id.to_def_id()); + let icx = ItemCtxt::new(tcx, def_id); let output = match tcx.hir().get(hir_id) { Node::TraitItem(item) => match item.kind { TraitItemKind::Fn(..) => { - let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id()); + let substs = InternalSubsts::identity_for_item(tcx, def_id); tcx.mk_fn_def(def_id.to_def_id(), substs) } TraitItemKind::Const(ty, body_id) => body_id .and_then(|body_id| { - is_suggestable_infer_ty(ty) - .then(|| infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident, "constant",)) + is_suggestable_infer_ty(ty).then(|| { + infer_placeholder_type( + tcx, def_id, body_id, ty.span, item.ident, "constant", + ) + }) }) .unwrap_or_else(|| icx.to_ty(ty)), TraitItemKind::Type(_, Some(ty)) => icx.to_ty(ty), @@ -271,7 +291,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<Ty<'_>> Node::ImplItem(item) => match item.kind { ImplItemKind::Fn(..) => { - let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id()); + let substs = InternalSubsts::identity_for_item(tcx, def_id); tcx.mk_fn_def(def_id.to_def_id(), substs) } ImplItemKind::Const(ty, body_id) => { @@ -316,22 +336,23 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<Ty<'_>> } } ItemKind::TyAlias(self_ty, _) => icx.to_ty(self_ty), - ItemKind::Impl(hir::Impl { self_ty, .. }) => { - match self_ty.find_self_aliases() { - spans if spans.len() > 0 => { - let guar = tcx.sess.emit_err(crate::errors::SelfInImplSelf { span: spans.into(), note: () }); - tcx.ty_error(guar) - }, - _ => icx.to_ty(*self_ty), + ItemKind::Impl(hir::Impl { self_ty, .. }) => match self_ty.find_self_aliases() { + spans if spans.len() > 0 => { + let guar = tcx.sess.emit_err(crate::errors::SelfInImplSelf { + span: spans.into(), + note: (), + }); + tcx.ty_error(guar) } + _ => icx.to_ty(*self_ty), }, ItemKind::Fn(..) => { - let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id()); + let substs = InternalSubsts::identity_for_item(tcx, def_id); tcx.mk_fn_def(def_id.to_def_id(), substs) } ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => { let def = tcx.adt_def(def_id); - let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id()); + let substs = InternalSubsts::identity_for_item(tcx, def_id); tcx.mk_adt(def, substs) } ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => { @@ -344,8 +365,11 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<Ty<'_>> in_trait, .. }) => { - if in_trait { - assert!(tcx.impl_defaultness(owner).has_value()); + if in_trait && !tcx.impl_defaultness(owner).has_value() { + span_bug!( + tcx.def_span(def_id), + "tried to get type of this RPITIT with no definition" + ); } find_opaque_ty_constraints_for_rpit(tcx, def_id, owner) } @@ -368,7 +392,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<Ty<'_>> Node::ForeignItem(foreign_item) => match foreign_item.kind { ForeignItemKind::Fn(..) => { - let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id()); + let substs = InternalSubsts::identity_for_item(tcx, def_id); tcx.mk_fn_def(def_id.to_def_id(), substs) } ForeignItemKind::Static(t, _) => icx.to_ty(t), @@ -380,7 +404,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<Ty<'_>> tcx.type_of(tcx.hir().get_parent_item(hir_id)).subst_identity() } VariantData::Tuple(..) => { - let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id()); + let substs = InternalSubsts::identity_for_item(tcx, def_id); tcx.mk_fn_def(def_id.to_def_id(), substs) } }, @@ -413,7 +437,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<Ty<'_>> Node::Expr(Expr { kind: ExprKind::ConstBlock(anon_const), .. }) if anon_const.hir_id == hir_id => { - let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id()); + let substs = InternalSubsts::identity_for_item(tcx, def_id); substs.as_inline_const().ty() } @@ -434,15 +458,12 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<Ty<'_>> tcx.adt_def(tcx.hir().get_parent_item(hir_id)).repr().discr_type().to_ty(tcx) } - Node::TypeBinding( - TypeBinding { - hir_id: binding_id, - kind: TypeBindingKind::Equality { term: Term::Const(e) }, - ident, - .. - }, - ) if let Node::TraitRef(trait_ref) = - tcx.hir().get_parent(*binding_id) + Node::TypeBinding(TypeBinding { + hir_id: binding_id, + kind: TypeBindingKind::Equality { term: Term::Const(e) }, + ident, + .. + }) if let Node::TraitRef(trait_ref) = tcx.hir().get_parent(*binding_id) && e.hir_id == hir_id => { let Some(trait_def_id) = trait_ref.trait_def_id() else { @@ -456,7 +477,9 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<Ty<'_>> def_id.to_def_id(), ); if let Some(assoc_item) = assoc_item { - tcx.type_of(assoc_item.def_id).subst_identity() + tcx.type_of(assoc_item.def_id) + .no_bound_vars() + .expect("const parameter types cannot be generic") } else { // FIXME(associated_const_equality): add a useful error message here. tcx.ty_error_with_message( @@ -466,10 +489,13 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<Ty<'_>> } } - Node::TypeBinding( - TypeBinding { hir_id: binding_id, gen_args, kind, ident, .. }, - ) if let Node::TraitRef(trait_ref) = - tcx.hir().get_parent(*binding_id) + Node::TypeBinding(TypeBinding { + hir_id: binding_id, + gen_args, + kind, + ident, + .. + }) if let Node::TraitRef(trait_ref) = tcx.hir().get_parent(*binding_id) && let Some((idx, _)) = gen_args.args.iter().enumerate().find(|(_, arg)| { if let GenericArg::Const(ct) = arg { @@ -498,15 +524,18 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<Ty<'_>> }, def_id.to_def_id(), ); - if let Some(param) - = assoc_item.map(|item| &tcx.generics_of(item.def_id).params[idx]).filter(|param| param.kind.is_ty_or_const()) + if let Some(assoc_item) = assoc_item + && let param = &tcx.generics_of(assoc_item.def_id).params[idx] + && matches!(param.kind, ty::GenericParamDefKind::Const { .. }) { - tcx.type_of(param.def_id).subst_identity() + tcx.type_of(param.def_id) + .no_bound_vars() + .expect("const parameter types cannot be generic") } else { // FIXME(associated_const_equality): add a useful error message here. tcx.ty_error_with_message( DUMMY_SP, - "Could not find associated const on trait", + "Could not find const param on associated item", ) } } @@ -574,7 +603,7 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T found: Option<ty::OpaqueHiddenType<'tcx>>, /// In the presence of dead code, typeck may figure out a hidden type - /// while borrowck will now. We collect these cases here and check at + /// while borrowck will not. We collect these cases here and check at /// the end that we actually found a type that matches (modulo regions). typeck_types: Vec<ty::OpaqueHiddenType<'tcx>>, } @@ -746,7 +775,7 @@ fn find_opaque_ty_constraints_for_rpit( // Use borrowck to get the type with unerased regions. let concrete_opaque_types = &self.tcx.mir_borrowck(def_id).concrete_opaque_types; debug!(?concrete_opaque_types); - for &(def_id, concrete_type) in concrete_opaque_types { + for (&def_id, &concrete_type) in concrete_opaque_types { if def_id != self.def_id { // Ignore constraints for other opaque types. continue; @@ -842,28 +871,6 @@ fn infer_placeholder_type<'a>( item_ident: Ident, kind: &'static str, ) -> Ty<'a> { - // Attempts to make the type nameable by turning FnDefs into FnPtrs. - struct MakeNameable<'tcx> { - tcx: TyCtxt<'tcx>, - } - - impl<'tcx> TypeFolder<TyCtxt<'tcx>> for MakeNameable<'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { - self.tcx - } - - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - let ty = match *ty.kind() { - ty::FnDef(def_id, substs) => { - self.tcx.mk_fn_ptr(self.tcx.fn_sig(def_id).subst(self.tcx, substs)) - } - _ => ty, - }; - - ty.super_fold_with(self) - } - } - let ty = tcx.diagnostic_only_typeck(def_id).node_type(body_id.hir_id); // If this came from a free `const` or `static mut?` item, diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 3e0692757..2a3a68348 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -5,7 +5,7 @@ use rustc_errors::{ error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, Handler, IntoDiagnostic, MultiSpan, }; -use rustc_macros::Diagnostic; +use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_middle::ty::Ty; use rustc_span::{symbol::Ident, Span, Symbol}; @@ -129,6 +129,18 @@ pub struct AssocTypeBindingNotAllowed { #[primary_span] #[label] pub span: Span, + + #[subdiagnostic] + pub fn_trait_expansion: Option<ParenthesizedFnTraitExpansion>, +} + +#[derive(Subdiagnostic)] +#[help(hir_analysis_parenthesized_fn_trait_expansion)] +pub struct ParenthesizedFnTraitExpansion { + #[primary_span] + pub span: Span, + + pub expanded_type: String, } #[derive(Diagnostic)] @@ -316,6 +328,14 @@ pub(crate) struct TrackCallerOnMain { } #[derive(Diagnostic)] +#[diag(hir_analysis_target_feature_on_main)] +pub(crate) struct TargetFeatureOnMain { + #[primary_span] + #[label(hir_analysis_target_feature_on_main)] + pub main: Span, +} + +#[derive(Diagnostic)] #[diag(hir_analysis_start_not_track_caller)] pub(crate) struct StartTrackCaller { #[primary_span] @@ -325,6 +345,15 @@ pub(crate) struct StartTrackCaller { } #[derive(Diagnostic)] +#[diag(hir_analysis_start_not_target_feature)] +pub(crate) struct StartTargetFeature { + #[primary_span] + pub span: Span, + #[label] + pub start: Span, +} + +#[derive(Diagnostic)] #[diag(hir_analysis_start_not_async, code = "E0752")] pub(crate) struct StartAsync { #[primary_span] @@ -399,3 +428,206 @@ pub(crate) enum CannotCaptureLateBoundInAnonConst { def_span: Span, }, } + +#[derive(Diagnostic)] +#[diag(hir_analysis_variances_of)] +pub(crate) struct VariancesOf { + #[primary_span] + pub span: Span, + pub variances_of: String, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_pass_to_variadic_function, code = "E0617")] +pub(crate) struct PassToVariadicFunction<'tcx, 'a> { + #[primary_span] + pub span: Span, + pub ty: Ty<'tcx>, + pub cast_ty: &'a str, + #[suggestion(code = "{replace}", applicability = "machine-applicable")] + pub sugg_span: Option<Span>, + pub replace: String, + #[help] + pub help: Option<()>, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_cast_thin_pointer_to_fat_pointer, code = "E0607")] +pub(crate) struct CastThinPointerToFatPointer<'tcx> { + #[primary_span] + pub span: Span, + pub expr_ty: Ty<'tcx>, + pub cast_ty: String, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_invalid_union_field, code = "E0740")] +pub(crate) struct InvalidUnionField { + #[primary_span] + pub field_span: Span, + #[subdiagnostic] + pub sugg: InvalidUnionFieldSuggestion, + #[note] + pub note: (), +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_return_type_notation_on_non_rpitit)] +pub(crate) struct ReturnTypeNotationOnNonRpitit<'tcx> { + #[primary_span] + pub span: Span, + pub ty: Ty<'tcx>, + #[label] + pub fn_span: Option<Span>, + #[note] + pub note: (), +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(hir_analysis_invalid_union_field_sugg, applicability = "machine-applicable")] +pub(crate) struct InvalidUnionFieldSuggestion { + #[suggestion_part(code = "std::mem::ManuallyDrop<")] + pub lo: Span, + #[suggestion_part(code = ">")] + pub hi: Span, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_return_type_notation_equality_bound)] +pub(crate) struct ReturnTypeNotationEqualityBound { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_return_type_notation_missing_method)] +pub(crate) struct ReturnTypeNotationMissingMethod { + #[primary_span] + pub span: Span, + pub trait_name: Symbol, + pub assoc_name: Symbol, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_placeholder_not_allowed_item_signatures, code = "E0121")] +pub(crate) struct PlaceholderNotAllowedItemSignatures { + #[primary_span] + #[label] + pub spans: Vec<Span>, + pub kind: String, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_associated_type_trait_uninferred_generic_params, code = "E0212")] +pub(crate) struct AssociatedTypeTraitUninferredGenericParams { + #[primary_span] + pub span: Span, + #[suggestion(style = "verbose", applicability = "maybe-incorrect", code = "{bound}")] + pub inferred_sugg: Option<Span>, + pub bound: String, + #[subdiagnostic] + pub mpart_sugg: Option<AssociatedTypeTraitUninferredGenericParamsMultipartSuggestion>, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion( + hir_analysis_associated_type_trait_uninferred_generic_params_multipart_suggestion, + applicability = "maybe-incorrect" +)] +pub(crate) struct AssociatedTypeTraitUninferredGenericParamsMultipartSuggestion { + #[suggestion_part(code = "{first}")] + pub fspan: Span, + pub first: String, + #[suggestion_part(code = "{second}")] + pub sspan: Span, + pub second: String, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_enum_discriminant_overflowed, code = "E0370")] +#[note] +pub(crate) struct EnumDiscriminantOverflowed { + #[primary_span] + #[label] + pub span: Span, + pub discr: String, + pub item_name: Symbol, + pub wrapped_discr: String, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_paren_sugar_attribute)] +#[help] +pub(crate) struct ParenSugarAttribute { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_must_implement_one_of_attribute)] +pub(crate) struct MustImplementOneOfAttribute { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_must_be_name_of_associated_function)] +pub(crate) struct MustBeNameOfAssociatedFunction { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_function_not_have_default_implementation)] +pub(crate) struct FunctionNotHaveDefaultImplementation { + #[primary_span] + pub span: Span, + #[note] + pub note_span: Span, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_must_implement_not_function)] +pub(crate) struct MustImplementNotFunction { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub span_note: MustImplementNotFunctionSpanNote, + #[subdiagnostic] + pub note: MustImplementNotFunctionNote, +} + +#[derive(Subdiagnostic)] +#[note(hir_analysis_must_implement_not_function_span_note)] +pub(crate) struct MustImplementNotFunctionSpanNote { + #[primary_span] + pub span: Span, +} + +#[derive(Subdiagnostic)] +#[note(hir_analysis_must_implement_not_function_note)] +pub(crate) struct MustImplementNotFunctionNote {} + +#[derive(Diagnostic)] +#[diag(hir_analysis_function_not_found_in_trait)] +pub(crate) struct FunctionNotFoundInTrait { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_functions_names_duplicated)] +#[note] +pub(crate) struct FunctionNamesDuplicated { + #[primary_span] + pub spans: Vec<Span>, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_simd_ffi_highly_experimental)] +#[help] +pub(crate) struct SIMDFFIHighlyExperimental { + #[primary_span] + pub span: Span, + pub snip: String, +} diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs index e330fcc78..8269a6dde 100644 --- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs @@ -7,7 +7,7 @@ use rustc_infer::traits::{ObligationCause, WellFormedLoc}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, Region, TyCtxt, TypeFoldable, TypeFolder}; use rustc_span::def_id::LocalDefId; -use rustc_trait_selection::traits; +use rustc_trait_selection::traits::{self, ObligationCtxt}; pub fn provide(providers: &mut Providers) { *providers = Providers { diagnostic_hir_wf_check, ..*providers }; @@ -31,7 +31,7 @@ fn diagnostic_hir_wf_check<'tcx>( tcx.sess .delay_span_bug(tcx.def_span(def_id), "Performed HIR wfcheck without an existing error!"); - let icx = ItemCtxt::new(tcx, def_id.to_def_id()); + let icx = ItemCtxt::new(tcx, def_id); // To perform HIR-based WF checking, we iterate over all HIR types // that occur 'inside' the item we're checking. For example, @@ -66,35 +66,35 @@ fn diagnostic_hir_wf_check<'tcx>( impl<'tcx> Visitor<'tcx> for HirWfCheck<'tcx> { fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) { let infcx = self.tcx.infer_ctxt().build(); + let ocx = ObligationCtxt::new(&infcx); + let tcx_ty = self.icx.to_ty(ty).fold_with(&mut EraseAllBoundRegions { tcx: self.tcx }); let cause = traits::ObligationCause::new( ty.span, self.def_id, traits::ObligationCauseCode::WellFormed(None), ); - let errors = traits::fully_solve_obligation( - &infcx, - traits::Obligation::new( - self.tcx, - cause, - self.param_env, - ty::Binder::dummy(ty::PredicateKind::WellFormed(tcx_ty.into())), - ), - ); - if !errors.is_empty() { - debug!("Wf-check got errors for {:?}: {:?}", ty, errors); - for error in errors { - if error.obligation.predicate == self.predicate { - // Save the cause from the greatest depth - this corresponds - // to picking more-specific types (e.g. `MyStruct<u8>`) - // over less-specific types (e.g. `Option<MyStruct<u8>>`) - if self.depth >= self.cause_depth { - self.cause = Some(error.obligation.cause); - self.cause_depth = self.depth - } + + ocx.register_obligation(traits::Obligation::new( + self.tcx, + cause, + self.param_env, + ty::PredicateKind::WellFormed(tcx_ty.into()), + )); + + for error in ocx.select_all_or_error() { + debug!("Wf-check got error for {:?}: {:?}", ty, error); + if error.obligation.predicate == self.predicate { + // Save the cause from the greatest depth - this corresponds + // to picking more-specific types (e.g. `MyStruct<u8>`) + // over less-specific types (e.g. `Option<MyStruct<u8>>`) + if self.depth >= self.cause_depth { + self.cause = Some(error.obligation.cause); + self.cause_depth = self.depth } } } + self.depth += 1; intravisit::walk_ty(self, ty); self.depth -= 1; diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index daa5d1570..eb2fc3952 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -168,20 +168,19 @@ fn get_impl_substs( let assumed_wf_types = ocx.assumed_wf_types(param_env, tcx.def_span(impl1_def_id), impl1_def_id); - let impl1_substs = InternalSubsts::identity_for_item(tcx, impl1_def_id.to_def_id()); + let impl1_substs = InternalSubsts::identity_for_item(tcx, impl1_def_id); let impl2_substs = translate_substs(infcx, param_env, impl1_def_id.to_def_id(), impl1_substs, impl2_node); let errors = ocx.select_all_or_error(); if !errors.is_empty() { - ocx.infcx.err_ctxt().report_fulfillment_errors(&errors, None); + ocx.infcx.err_ctxt().report_fulfillment_errors(&errors); return None; } let implied_bounds = infcx.implied_bounds_tys(param_env, impl1_def_id, assumed_wf_types); - let outlives_env = OutlivesEnvironment::with_bounds(param_env, Some(infcx), implied_bounds); - let _ = - infcx.err_ctxt().check_region_obligations_and_report_errors(impl1_def_id, &outlives_env); + let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); + let _ = ocx.resolve_regions_and_report_errors(impl1_def_id, &outlives_env); let Ok(impl2_substs) = infcx.fully_resolve(impl2_substs) else { let span = tcx.def_span(impl1_def_id); tcx.sess.emit_err(SubstsOnOverriddenImpl { span }); @@ -318,30 +317,20 @@ fn check_predicates<'tcx>( span: Span, ) { let instantiated = tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs); - let impl1_predicates: Vec<_> = traits::elaborate_predicates_with_span( - tcx, - std::iter::zip( - instantiated.predicates, - // Don't drop predicates (unsound!) because `spans` is too short - instantiated.spans.into_iter().chain(std::iter::repeat(span)), - ), - ) - .map(|obligation| (obligation.predicate, obligation.cause.span)) - .collect(); + let impl1_predicates: Vec<_> = traits::elaborate(tcx, instantiated.into_iter()).collect(); let mut impl2_predicates = if impl2_node.is_from_trait() { // Always applicable traits have to be always applicable without any // assumptions. Vec::new() } else { - traits::elaborate_predicates( + traits::elaborate( tcx, tcx.predicates_of(impl2_node.def_id()) .instantiate(tcx, impl2_substs) .predicates .into_iter(), ) - .map(|obligation| obligation.predicate) .collect() }; debug!(?impl1_predicates, ?impl2_predicates); @@ -361,12 +350,16 @@ fn check_predicates<'tcx>( // which is sound because we forbid impls like the following // // impl<D: Debug> AlwaysApplicable for D { } - let always_applicable_traits = impl1_predicates.iter().copied().filter(|&(predicate, _)| { - matches!( - trait_predicate_kind(tcx, predicate), - Some(TraitSpecializationKind::AlwaysApplicable) - ) - }); + let always_applicable_traits = impl1_predicates + .iter() + .copied() + .filter(|&(predicate, _)| { + matches!( + trait_predicate_kind(tcx, predicate), + Some(TraitSpecializationKind::AlwaysApplicable) + ) + }) + .map(|(pred, _span)| pred); // Include the well-formed predicates of the type parameters of the impl. for arg in tcx.impl_trait_ref(impl1_def_id).unwrap().subst_identity().substs { @@ -376,14 +369,10 @@ fn check_predicates<'tcx>( .unwrap(); assert!(!obligations.needs_infer()); - impl2_predicates.extend( - traits::elaborate_obligations(tcx, obligations).map(|obligation| obligation.predicate), - ) + impl2_predicates + .extend(traits::elaborate(tcx, obligations).map(|obligation| obligation.predicate)) } - impl2_predicates.extend( - traits::elaborate_predicates_with_span(tcx, always_applicable_traits) - .map(|obligation| obligation.predicate), - ); + impl2_predicates.extend(traits::elaborate(tcx, always_applicable_traits)); for (predicate, span) in impl1_predicates { if !impl2_predicates.iter().any(|pred2| trait_predicates_eq(tcx, predicate, *pred2, span)) { @@ -528,7 +517,7 @@ fn trait_predicate_kind<'tcx>( | ty::PredicateKind::Clause(ty::Clause::TypeOutlives(_)) | ty::PredicateKind::Clause(ty::Clause::Projection(_)) | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) - | ty::PredicateKind::AliasEq(..) + | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::WellFormed(_) | ty::PredicateKind::Subtype(_) | ty::PredicateKind::Coerce(_) diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 33c132fd5..27e561803 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -67,10 +67,9 @@ This API is completely unstable and subject to change. #![feature(let_chains)] #![feature(min_specialization)] #![feature(never_type)] -#![feature(once_cell)] +#![feature(lazy_cell)] #![feature(slice_partition_dedup)] #![feature(try_blocks)] -#![feature(is_some_and)] #![feature(type_alias_impl_trait)] #![recursion_limit = "256"] @@ -102,7 +101,7 @@ use rustc_errors::ErrorGuaranteed; use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; use rustc_hir as hir; use rustc_hir::Node; -use rustc_infer::infer::{InferOk, TyCtxtInferExt}; +use rustc_infer::infer::TyCtxtInferExt; use rustc_macros::fluent_messages; use rustc_middle::middle; use rustc_middle::ty::query::Providers; @@ -113,14 +112,14 @@ use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID}; use rustc_span::{symbol::sym, Span, DUMMY_SP}; use rustc_target::spec::abi::Abi; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _; -use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode}; +use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, ObligationCtxt}; use std::ops::Not; use astconv::AstConv; use bounds::Bounds; -fluent_messages! { "../locales/en-US.ftl" } +fluent_messages! { "../messages.ftl" } fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span) { const CONVENTIONS_UNSTABLE: &str = "`C`, `cdecl`, `win64`, `sysv64` or `efiapi`"; @@ -160,24 +159,21 @@ fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi fn require_same_types<'tcx>( tcx: TyCtxt<'tcx>, cause: &ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, expected: Ty<'tcx>, actual: Ty<'tcx>, -) -> bool { +) { let infcx = &tcx.infer_ctxt().build(); - let param_env = ty::ParamEnv::empty(); - let errors = match infcx.at(cause, param_env).eq(expected, actual) { - Ok(InferOk { obligations, .. }) => traits::fully_solve_obligations(infcx, obligations), + let ocx = ObligationCtxt::new(infcx); + match ocx.eq(cause, param_env, expected, actual) { + Ok(()) => { + let errors = ocx.select_all_or_error(); + if !errors.is_empty() { + infcx.err_ctxt().report_fulfillment_errors(&errors); + } + } Err(err) => { infcx.err_ctxt().report_mismatched_types(cause, expected, actual, err).emit(); - return false; - } - }; - - match &errors[..] { - [] => true, - errors => { - infcx.err_ctxt().report_fulfillment_errors(errors, None); - false } } } @@ -283,10 +279,21 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { error = true; } + if !tcx.codegen_fn_attrs(main_def_id).target_features.is_empty() + // Calling functions with `#[target_feature]` is not unsafe on WASM, see #84988 + && !tcx.sess.target.is_like_wasm + && !tcx.sess.opts.actually_rustdoc + { + tcx.sess.emit_err(errors::TargetFeatureOnMain { main: main_span }); + error = true; + } + if error { return; } + // Main should have no WC, so empty param env is OK here. + let param_env = ty::ParamEnv::empty(); let expected_return_type; if let Some(term_did) = tcx.lang_items().termination() { let return_ty = main_fnsig.output(); @@ -297,8 +304,6 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { } let return_ty = return_ty.skip_binder(); let infcx = tcx.infer_ctxt().build(); - // Main should have no WC, so empty param env is OK here. - let param_env = ty::ParamEnv::empty(); let cause = traits::ObligationCause::new( return_ty_span, main_diagnostics_def_id, @@ -309,7 +314,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { ocx.register_bound(cause, param_env, norm_return_ty, term_did); let errors = ocx.select_all_or_error(); if !errors.is_empty() { - infcx.err_ctxt().report_fulfillment_errors(&errors, None); + infcx.err_ctxt().report_fulfillment_errors(&errors); error = true; } // now we can take the return type of the given main function @@ -334,6 +339,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { main_diagnostics_def_id, ObligationCauseCode::MainFunctionType, ), + param_env, se_ty, tcx.mk_fn_ptr(main_fnsig), ); @@ -373,6 +379,18 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) { }); error = true; } + if attr.has_name(sym::target_feature) + // Calling functions with `#[target_feature]` is + // not unsafe on WASM, see #84988 + && !tcx.sess.target.is_like_wasm + && !tcx.sess.opts.actually_rustdoc + { + tcx.sess.emit_err(errors::StartTargetFeature { + span: attr.span, + start: start_span, + }); + error = true; + } } if error { @@ -396,6 +414,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) { start_def_id, ObligationCauseCode::StartFunctionType, ), + ty::ParamEnv::empty(), // start should not have any where bounds. se_ty, tcx.mk_fn_ptr(tcx.fn_sig(start_def_id).subst_identity()), ); @@ -492,7 +511,7 @@ pub fn hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'_>) -> Ty<'tcx> { // def-ID that will be used to determine the traits/predicates in // scope. This is derived from the enclosing item-like thing. let env_def_id = tcx.hir().get_parent_item(hir_ty.hir_id); - let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id()); + let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.def_id); item_cx.astconv().ast_ty_to_ty(hir_ty) } @@ -505,7 +524,7 @@ pub fn hir_trait_to_predicates<'tcx>( // def-ID that will be used to determine the traits/predicates in // scope. This is derived from the enclosing item-like thing. let env_def_id = tcx.hir().get_parent_item(hir_trait.hir_ref_id); - let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id()); + let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.def_id); let mut bounds = Bounds::default(); let _ = &item_cx.astconv().instantiate_poly_trait_ref( hir_trait, diff --git a/compiler/rustc_hir_analysis/src/outlives/explicit.rs b/compiler/rustc_hir_analysis/src/outlives/explicit.rs index 9ee678597..357deb07b 100644 --- a/compiler/rustc_hir_analysis/src/outlives/explicit.rs +++ b/compiler/rustc_hir_analysis/src/outlives/explicit.rs @@ -56,7 +56,7 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> { | ty::PredicateKind::Clause(ty::Clause::Projection(..)) | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) | ty::PredicateKind::WellFormed(..) - | ty::PredicateKind::AliasEq(..) + | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::Subtype(..) diff --git a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs index a8b33c74b..d53c429ca 100644 --- a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs +++ b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs @@ -1,7 +1,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; -use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{GenericArg, GenericArgKind}; use rustc_span::Span; diff --git a/compiler/rustc_hir_analysis/src/outlives/mod.rs b/compiler/rustc_hir_analysis/src/outlives/mod.rs index 81fe32000..da72d2584 100644 --- a/compiler/rustc_hir_analysis/src/outlives/mod.rs +++ b/compiler/rustc_hir_analysis/src/outlives/mod.rs @@ -1,6 +1,6 @@ use hir::Node; use rustc_hir as hir; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::LocalDefId; use rustc_middle::ty::query::Providers; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::{self, CratePredicatesMap, TyCtxt}; @@ -17,8 +17,8 @@ pub fn provide(providers: &mut Providers) { *providers = Providers { inferred_outlives_of, inferred_outlives_crate, ..*providers }; } -fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[(ty::Clause<'_>, Span)] { - let id = tcx.hir().local_def_id_to_hir_id(item_def_id.expect_local()); +fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[(ty::Clause<'_>, Span)] { + let id = tcx.hir().local_def_id_to_hir_id(item_def_id); if matches!(tcx.def_kind(item_def_id), hir::def::DefKind::AnonConst) && tcx.lazy_normalization() { @@ -45,7 +45,8 @@ fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[(ty::Clause<'_ hir::ItemKind::Struct(..) | hir::ItemKind::Enum(..) | hir::ItemKind::Union(..) => { let crate_map = tcx.inferred_outlives_crate(()); - let predicates = crate_map.predicates.get(&item_def_id).copied().unwrap_or(&[]); + let predicates = + crate_map.predicates.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]); if tcx.has_attr(item_def_id, sym::rustc_outlives) { let mut pred: Vec<String> = predicates diff --git a/compiler/rustc_hir_analysis/src/outlives/test.rs b/compiler/rustc_hir_analysis/src/outlives/test.rs index fa2ac5659..60f8e246a 100644 --- a/compiler/rustc_hir_analysis/src/outlives/test.rs +++ b/compiler/rustc_hir_analysis/src/outlives/test.rs @@ -6,7 +6,7 @@ pub fn test_inferred_outlives(tcx: TyCtxt<'_>) { for id in tcx.hir().items() { // For unit testing: check for a special "rustc_outlives" // attribute and report an error with various results if found. - if tcx.has_attr(id.owner_id.to_def_id(), sym::rustc_outlives) { + if tcx.has_attr(id.owner_id, sym::rustc_outlives) { let inferred_outlives_of = tcx.inferred_outlives_of(id.owner_id); struct_span_err!( tcx.sess, diff --git a/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs b/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs index 089491bef..0bfbf99cb 100644 --- a/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs +++ b/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs @@ -1,5 +1,5 @@ -use crate::structured_errors::StructuredDiagnostic; -use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticId, ErrorGuaranteed}; +use crate::{errors, structured_errors::StructuredDiagnostic}; +use rustc_errors::{DiagnosticBuilder, DiagnosticId, ErrorGuaranteed}; use rustc_middle::ty::{Ty, TypeVisitableExt}; use rustc_session::Session; use rustc_span::Span; @@ -21,27 +21,26 @@ impl<'tcx> StructuredDiagnostic<'tcx> for MissingCastForVariadicArg<'tcx, '_> { } fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - let mut err = self.sess.struct_span_err_with_code( - self.span, - &format!("can't pass `{}` to variadic function", self.ty), - self.code(), - ); + let (sugg_span, replace, help) = + if let Ok(snippet) = self.sess.source_map().span_to_snippet(self.span) { + (Some(self.span), format!("{} as {}", snippet, self.cast_ty), None) + } else { + (None, "".to_string(), Some(())) + }; + + let mut err = self.sess.create_err(errors::PassToVariadicFunction { + span: self.span, + ty: self.ty, + cast_ty: self.cast_ty, + help, + replace, + sugg_span, + }); if self.ty.references_error() { err.downgrade_to_delayed_bug(); } - if let Ok(snippet) = self.sess.source_map().span_to_snippet(self.span) { - err.span_suggestion( - self.span, - &format!("cast the value to `{}`", self.cast_ty), - format!("{} as {}", snippet, self.cast_ty), - Applicability::MachineApplicable, - ); - } else { - err.help(&format!("cast the value to `{}`", self.cast_ty)); - } - err } diff --git a/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs b/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs index 3b9fb3678..910417abe 100644 --- a/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs +++ b/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs @@ -1,4 +1,4 @@ -use crate::structured_errors::StructuredDiagnostic; +use crate::{errors, structured_errors::StructuredDiagnostic}; use rustc_errors::{DiagnosticBuilder, DiagnosticId, ErrorGuaranteed}; use rustc_middle::ty::{Ty, TypeVisitableExt}; use rustc_session::Session; @@ -21,14 +21,11 @@ impl<'tcx> StructuredDiagnostic<'tcx> for SizedUnsizedCast<'tcx> { } fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - let mut err = self.sess.struct_span_err_with_code( - self.span, - &format!( - "cannot cast thin pointer `{}` to fat pointer `{}`", - self.expr_ty, self.cast_ty - ), - self.code(), - ); + let mut err = self.sess.create_err(errors::CastThinPointerToFatPointer { + span: self.span, + expr_ty: self.expr_ty, + cast_ty: self.cast_ty.to_owned(), + }); if self.expr_ty.references_error() { err.downgrade_to_delayed_bug(); diff --git a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs index cae884ae8..8f4d81ec3 100644 --- a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs +++ b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs @@ -565,7 +565,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { /// type Map = HashMap<String>; /// ``` fn suggest_adding_args(&self, err: &mut Diagnostic) { - if self.gen_args.parenthesized { + if self.gen_args.parenthesized != hir::GenericArgsParentheses::No { return; } @@ -962,7 +962,11 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { let msg = format!( "remove these {}generics", - if self.gen_args.parenthesized { "parenthetical " } else { "" }, + if self.gen_args.parenthesized == hir::GenericArgsParentheses::ParenSugar { + "parenthetical " + } else { + "" + }, ); err.span_suggestion(span, &msg, "", Applicability::MaybeIncorrect); diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs index 5d5c8ca60..0a45119ff 100644 --- a/compiler/rustc_hir_analysis/src/variance/mod.rs +++ b/compiler/rustc_hir_analysis/src/variance/mod.rs @@ -8,7 +8,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, CrateVariancesMap, SubstsRef, Ty, TyCtxt}; -use rustc_middle::ty::{DefIdTree, TypeSuperVisitable, TypeVisitable}; +use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable}; use std::ops::ControlFlow; /// Defines the `TermsContext` basically houses an arena where we can @@ -38,7 +38,7 @@ fn crate_variances(tcx: TyCtxt<'_>, (): ()) -> CrateVariancesMap<'_> { solve::solve_constraints(constraints_cx) } -fn variances_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[ty::Variance] { +fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] { // Skip items with no generics - there's nothing to infer in them. if tcx.generics_of(item_def_id).count() == 0 { return &[]; @@ -53,7 +53,7 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[ty::Variance] { | DefKind::Variant | DefKind::Ctor(..) => {} DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder => { - return variance_of_opaque(tcx, item_def_id.expect_local()); + return variance_of_opaque(tcx, item_def_id); } _ => { // Variance not relevant. @@ -64,7 +64,7 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[ty::Variance] { // Everything else must be inferred. let crate_map = tcx.crate_variances(()); - crate_map.variances.get(&item_def_id).copied().unwrap_or(&[]) + crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]) } #[instrument(level = "trace", skip(tcx), ret)] @@ -112,10 +112,14 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { match t.kind() { ty::Alias(_, ty::AliasTy { def_id, substs, .. }) - if matches!( - self.tcx.def_kind(*def_id), - DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder - ) => + if matches!(self.tcx.def_kind(*def_id), DefKind::OpaqueTy) => + { + self.visit_opaque(*def_id, substs) + } + // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty) check whether this is necessary + // at all for RPITITs. + ty::Alias(_, ty::AliasTy { def_id, substs, .. }) + if self.tcx.is_impl_trait_in_trait(*def_id) => { self.visit_opaque(*def_id, substs) } @@ -148,7 +152,7 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc let mut collector = OpaqueTypeLifetimeCollector { tcx, root_def_id: item_def_id.to_def_id(), variances }; - let id_substs = ty::InternalSubsts::identity_for_item(tcx, item_def_id.to_def_id()); + let id_substs = ty::InternalSubsts::identity_for_item(tcx, item_def_id); for pred in tcx.bound_explicit_item_bounds(item_def_id.to_def_id()).transpose_iter() { let pred = pred.map_bound(|(pred, _)| *pred).subst(tcx, id_substs); debug!(?pred); diff --git a/compiler/rustc_hir_analysis/src/variance/test.rs b/compiler/rustc_hir_analysis/src/variance/test.rs index 5feeb92d3..d57d05d76 100644 --- a/compiler/rustc_hir_analysis/src/variance/test.rs +++ b/compiler/rustc_hir_analysis/src/variance/test.rs @@ -1,14 +1,19 @@ use rustc_middle::ty::TyCtxt; use rustc_span::symbol::sym; +use crate::errors; + pub fn test_variance(tcx: TyCtxt<'_>) { // For unit testing: check for a special "rustc_variance" // attribute and report an error with various results if found. for id in tcx.hir().items() { - if tcx.has_attr(id.owner_id.to_def_id(), sym::rustc_variance) { + if tcx.has_attr(id.owner_id, sym::rustc_variance) { let variances_of = tcx.variances_of(id.owner_id); - tcx.sess.struct_span_err(tcx.def_span(id.owner_id), format!("{variances_of:?}")).emit(); + tcx.sess.emit_err(errors::VariancesOf { + span: tcx.def_span(id.owner_id), + variances_of: format!("{variances_of:?}"), + }); } } } |