diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 1c14c645d474c..630c65ea0a450 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -230,7 +230,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let old_attrs = self.curr_owner.attrs.get(&ex.hir_id.local_id).copied().unwrap_or(&[]); let new_attrs = self - .lower_attrs_vec(&e.attrs, e.span, ex.hir_id, Target::from_expr(e)) + .lower_attrs_vec(&e.attrs, e.span, ex.hir_id, Target::from_expr(e), None) .into_iter() .chain(old_attrs.iter().cloned()); let new_attrs = &*self.arena.alloc_from_iter(new_attrs); diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index b5e28d21a2613..256da9d6c7d5b 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -215,6 +215,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &i.attrs, i.span, Target::from_ast_item(i), + Some(i), &extra_hir_attributes, ); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index a27dc47bf27c3..a5896f495847d 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1182,7 +1182,7 @@ impl<'hir> LoweringContext<'_, 'hir> { target_span: Span, target: Target, ) -> &'hir [hir::Attribute] { - self.lower_attrs_with_extra(id, attrs, target_span, target, &[]) + self.lower_attrs_with_extra(id, attrs, target_span, target, None, &[]) } fn lower_attrs_with_extra( @@ -1191,13 +1191,14 @@ impl<'hir> LoweringContext<'_, 'hir> { attrs: &[Attribute], target_span: Span, target: Target, + target_item: Option<&ast::Item>, extra_hir_attributes: &[hir::Attribute], ) -> &'hir [hir::Attribute] { if attrs.is_empty() && extra_hir_attributes.is_empty() { &[] } else { let mut lowered_attrs = - self.lower_attrs_vec(attrs, self.lower_span(target_span), id, target); + self.lower_attrs_vec(attrs, self.lower_span(target_span), id, target, target_item); lowered_attrs.extend(extra_hir_attributes.iter().cloned()); assert_eq!(id.owner, self.curr_owner.owner_id); @@ -1224,12 +1225,14 @@ impl<'hir> LoweringContext<'_, 'hir> { target_span: Span, target_hir_id: HirId, target: Target, + target_item: Option<&ast::Item>, ) -> Vec { let l = self.span_lowerer(); self.attribute_parser.parse_attribute_list( attrs, target_span, target, + target_item, |s| l.lower(s), |lint_id, span, kind| { self.curr_owner.delayed_lints.push(DelayedLint { @@ -2685,7 +2688,7 @@ impl<'hir> LoweringContext<'_, 'hir> { match (body, kind) { (body, ConstItemKind::Body) => { let is_direct = |body| { - if self.tcx.features().macroless_generic_const_args() { + if self.tcx.features().macroless_const_item_generic_const_args() { self.can_lower_expr_to_const_arg_direct( body, DirectConstArgContext::MacrolessMinGenericConstArgs, diff --git a/compiler/rustc_attr_parsing/src/attributes/doc.rs b/compiler/rustc_attr_parsing/src/attributes/doc.rs index 6cce64d700a63..7aeedc1493027 100644 --- a/compiler/rustc_attr_parsing/src/attributes/doc.rs +++ b/compiler/rustc_attr_parsing/src/attributes/doc.rs @@ -705,16 +705,7 @@ impl DocParser { fn accept_single_doc_attr(&mut self, cx: &mut AcceptContext<'_, '_>, args: &ArgParser) { match args { - ArgParser::NoArgs => { - let suggestions = cx.adcx().suggestions(); - let span = cx.inner_span; - cx.emit_lint( - INVALID_DOC_ATTRIBUTES, - IllFormedAttributeInput::new(&suggestions, None, None), - span, - ); - } - ArgParser::List(items) => { + ArgParser::List(items) if !items.is_empty() => { for i in items.mixed() { match i { MetaItemOrLitParser::MetaItemParser(mip) => { @@ -739,6 +730,15 @@ impl DocParser { ); } } + _ => { + let suggestions = cx.adcx().suggestions(); + let span = cx.inner_span; + cx.emit_lint( + INVALID_DOC_ATTRIBUTES, + IllFormedAttributeInput::new(&suggestions, None, None), + span, + ); + } } } } @@ -749,7 +749,6 @@ impl AttributeParser for DocParser { template!( List: &[ "alias", - "attribute", "hidden", "html_favicon_url", "html_logo_url", @@ -762,19 +761,10 @@ impl AttributeParser for DocParser { "masked", "cfg", "notable_trait", - "keyword", - "fake_variadic", - "search_unbox", - "rust_logo", "auto_cfg", "test", - "spotlight", - "include", - "no_default_passes", - "passes", - "plugins", ], - NameValueStr: "string" + NameValueStr: "doc comment" ), AttributeStability::Stable, // Some parts of the attribute are unstable, manually checked in parser |this, cx, args| { diff --git a/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs b/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs index 48e97784a2286..30fdadf95e4ce 100644 --- a/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs +++ b/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs @@ -1,11 +1,8 @@ -use rustc_attr_ir::AttributeKind; -use rustc_attr_ir::target::Target; +use rustc_ast::{ItemKind, VariantData}; use rustc_feature::AttributeStability; -use rustc_span::{Span, Symbol, sym}; -use crate::attributes::{NoArgsAttributeParser, OnDuplicate}; -use crate::target_checking::AllowedTargets; -use crate::target_checking::Policy::{Allow, Warn}; +use super::prelude::*; +use crate::diagnostics::NonExhaustiveWithDefaultFieldValues; pub(crate) struct NonExhaustiveParser; @@ -23,4 +20,23 @@ impl NoArgsAttributeParser for NonExhaustiveParser { ]); const STABILITY: AttributeStability = AttributeStability::Stable; const CREATE: fn(Span) -> AttributeKind = AttributeKind::NonExhaustive; + + fn finalize_check(cx: &FinalizeCheckContext<'_, '_>, attr_span: Span) { + if cx.target != Target::Struct { + return; + } + + let item = cx.target_item.expect("missing AST target item for Target::Struct"); + let ItemKind::Struct(_, _, data) = &item.kind else { + panic!("expected struct AST target item for Target::Struct"); + }; + if let VariantData::Struct { fields, .. } = data + && fields.iter().any(|f| f.default_value().is_some()) + { + cx.emit_err(NonExhaustiveWithDefaultFieldValues { + attr_span, + defn_span: cx.target_span, + }); + } + } } diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index cf99311cc0cfc..8d03c441acf16 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -833,6 +833,10 @@ pub(crate) struct FinalizeCheckContext<'p, 'sess> { /// /// Unlike [`all_attrs`](Self::all_attrs), this contains the fully parsed attributes. pub(crate) parsed_attrs: &'p [Attribute], + + /// The AST item these attributes were applied to, when the target is an item. + /// Used by `finalize_check` to inspect item structure that is not encoded in [`Target`]. + pub(crate) target_item: Option<&'p rustc_ast::ast::Item>, } impl<'p, 'sess: 'p> Deref for FinalizeCheckContext<'p, 'sess> { diff --git a/compiler/rustc_attr_parsing/src/diagnostics.rs b/compiler/rustc_attr_parsing/src/diagnostics.rs index 663915e39dccd..aeaada0e61409 100644 --- a/compiler/rustc_attr_parsing/src/diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/diagnostics.rs @@ -1169,6 +1169,15 @@ pub(crate) struct DeprecatedAnnotationHasNoEffect { pub span: Span, } +#[derive(Diagnostic)] +#[diag("`#[non_exhaustive]` can't be used to annotate items with default field values")] +pub(crate) struct NonExhaustiveWithDefaultFieldValues { + #[primary_span] + pub attr_span: Span, + #[label("this struct has default field values")] + pub defn_span: Span, +} + #[derive(Diagnostic)] #[diag("expected single version literal")] pub(crate) struct ExpectedSingleVersionLiteral { diff --git a/compiler/rustc_attr_parsing/src/interface.rs b/compiler/rustc_attr_parsing/src/interface.rs index 240f437828259..1cecce8fd43ef 100644 --- a/compiler/rustc_attr_parsing/src/interface.rs +++ b/compiler/rustc_attr_parsing/src/interface.rs @@ -161,6 +161,7 @@ impl<'sess> AttributeParser<'sess> { attrs, target_span, target, + None, std::convert::identity, |lint_id, span, kind| { sess.psess.dyn_buffer_lint_sess(lint_id.lint, span, target_node_id, kind.0) @@ -315,6 +316,7 @@ impl<'sess> AttributeParser<'sess> { attrs: &[ast::Attribute], target_span: Span, target: Target, + target_item: Option<&ast::Item>, lower_span: impl Copy + Fn(Span) -> Span, mut emit_lint: impl FnMut(LintId, MultiSpan, EmitAttribute), ) -> Vec { @@ -521,6 +523,7 @@ impl<'sess> AttributeParser<'sess> { }, all_attrs: &attr_paths, parsed_attrs: &attributes, + target_item, }, attr_span, ); diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 8f9e57877ca8c..8c0cb78b68b2e 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -954,7 +954,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { tcx, self.infcx.typing_env(self.infcx.param_env), fn_did, - self.infcx.resolve_vars_if_possible(args.no_bound_vars().unwrap()), + self.infcx.deeply_resolve_ignoring_regions(args.no_bound_vars().unwrap()), ) else { return; }; diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs index a154078b7ad86..ad15c5750b092 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs @@ -73,7 +73,7 @@ pub(crate) fn clone_and_resolve_opaque_types<'tcx>( let opaque_types = opaque_types .into_iter() .map(|entry| { - fold_regions(infcx.tcx, infcx.resolve_vars_if_possible(entry), |r, _| { + fold_regions(infcx.tcx, infcx.deeply_resolve_ignoring_regions(entry), |r, _| { let vid = if let ty::RePlaceholder(placeholder) = r.kind() { constraints.placeholder_region(infcx, placeholder).as_var() } else { diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index e20f9a646a953..9790cece59196 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -157,7 +157,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { GenericArgKind::Type(mut t1) => { // Scraped constraints may have had inference vars. - t1 = self.infcx.resolve_vars_if_possible(t1); + t1 = self.infcx.deeply_resolve_ignoring_regions(t1); let implicit_region_bound = ty::Region::new_var(tcx, universal_regions.implicit_region_bound()); diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index c922d1a9f0f86..10974a5157b10 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -145,7 +145,7 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> { ty, )?; let new_var = - infcx.resolve_vars_if_possible(Ty::new_infer(infcx.tcx, ty::TyVar(ty_vid))); + infcx.deeply_resolve_ignoring_regions(Ty::new_infer(infcx.tcx, ty::TyVar(ty_vid))); // Any regions in this new type must be live everywhere, so we mark them as such. // (It may be that it only needs to be live where the opaque type itself is - which diff --git a/compiler/rustc_builtin_macros/src/deriving/bounds.rs b/compiler/rustc_builtin_macros/src/deriving/bounds.rs deleted file mode 100644 index 48fdb4dd39ce2..0000000000000 --- a/compiler/rustc_builtin_macros/src/deriving/bounds.rs +++ /dev/null @@ -1,56 +0,0 @@ -use rustc_ast::{MetaItem, Safety}; -use rustc_expand::base::{Annotatable, ExtCtxt}; -use rustc_span::Span; - -use crate::deriving::generic::*; -use crate::deriving::path_std; - -pub(crate) fn expand_deriving_copy( - cx: &ExtCtxt<'_>, - span: Span, - mitem: &MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable), - is_const: bool, -) { - let trait_def = TraitDef { - span, - path: path_std!(marker::Copy), - skip_path_as_bound: false, - needs_copy_as_bound_if_packed: false, - additional_bounds: SmallVec::new(), - supports_unions: true, - methods: SmallVec::new(), - associated_types: SmallVec::new(), - is_const, - safety: Safety::Default, - document: true, - }; - - trait_def.expand(cx, mitem, item, push); -} - -pub(crate) fn expand_deriving_const_param_ty( - cx: &ExtCtxt<'_>, - span: Span, - mitem: &MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable), - is_const: bool, -) { - let trait_def = TraitDef { - span, - path: path_std!(marker::ConstParamTy_), - skip_path_as_bound: false, - needs_copy_as_bound_if_packed: false, - additional_bounds: smallvec![ty::Ty::Path(path_std!(cmp::Eq))], - supports_unions: false, - methods: SmallVec::new(), - associated_types: SmallVec::new(), - is_const, - safety: Safety::Default, - document: true, - }; - - trait_def.expand(cx, mitem, item, push); -} diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs index b4374e32f6051..f072b4b9e5cd1 100644 --- a/compiler/rustc_builtin_macros/src/deriving/clone.rs +++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs @@ -1,6 +1,6 @@ use rustc_ast::{self as ast, Generics, ItemKind, MetaItem, Safety, VariantData}; use rustc_data_structures::fx::FxHashSet; -use rustc_expand::base::{Annotatable, ExtCtxt}; +use rustc_expand::base::ExtCtxt; use rustc_span::{DUMMY_SP, Ident, Span, kw, sym}; use thin_vec::{ThinVec, thin_vec}; @@ -12,8 +12,8 @@ pub(crate) fn expand_deriving_clone( cx: &ExtCtxt<'_>, span: Span, mitem: &MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable), + item: &ast::Item, + push: &mut dyn FnMut(Box), is_const: bool, ) { // The simple form is `fn clone(&self) -> Self { *self }`, possibly with @@ -32,35 +32,30 @@ pub(crate) fn expand_deriving_clone( let bounds; let substructure; let is_simple; - match item { - Annotatable::Item(annitem) => match &annitem.kind { - ItemKind::Struct(_, Generics { params, .. }, _) - | ItemKind::Enum(_, Generics { params, .. }, _) => { - let container_id = cx.current_expansion.id.expn_data().parent.expect_local(); - let has_derive_copy = cx.resolver.has_derive_copy(container_id); - bounds = smallvec![]; - if has_derive_copy - && !params - .iter() - .any(|param| matches!(param.kind, ast::GenericParamKind::Type { .. })) - { - is_simple = true; - substructure = - combine_substructure(|c, s, sub| cs_clone_simple(c, s, sub, false)); - } else { - is_simple = false; - substructure = combine_substructure(cs_clone); - } - } - ItemKind::Union(..) => { - bounds = smallvec![Path(path_std!(marker::Copy))]; + match &item.kind { + ItemKind::Struct(_, Generics { params, .. }, _) + | ItemKind::Enum(_, Generics { params, .. }, _) => { + let container_id = cx.current_expansion.id.expn_data().parent.expect_local(); + let has_derive_copy = cx.resolver.has_derive_copy(container_id); + bounds = smallvec![]; + if has_derive_copy + && !params + .iter() + .any(|param| matches!(param.kind, ast::GenericParamKind::Type { .. })) + { is_simple = true; - substructure = combine_substructure(|c, s, sub| cs_clone_simple(c, s, sub, true)); + substructure = combine_substructure(|c, s, sub| cs_clone_simple(c, s, sub, false)); + } else { + is_simple = false; + substructure = combine_substructure(cs_clone); } - _ => cx.dcx().span_bug(span, "`#[derive(Clone)]` on wrong item kind"), - }, - - _ => cx.dcx().span_bug(span, "`#[derive(Clone)]` on trait item or impl item"), + } + ItemKind::Union(..) => { + bounds = smallvec![Path(path_std!(marker::Copy))]; + is_simple = true; + substructure = combine_substructure(|c, s, sub| cs_clone_simple(c, s, sub, true)); + } + _ => cx.dcx().span_bug(span, "`#[derive(Clone)]` on wrong item kind"), } // If the clone method is just copying the value, also mark the type as @@ -82,7 +77,7 @@ pub(crate) fn expand_deriving_clone( document: false, }; - trivial_def.expand_ext(cx, mitem, item, push, true); + trivial_def.expand(cx, mitem, item, push); } let trait_def = TraitDef { diff --git a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs index 80296a43ee490..58b4734b132c3 100644 --- a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs +++ b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs @@ -1,13 +1,13 @@ use ast::HasAttrs; use rustc_ast::mut_visit::MutVisitor; -use rustc_ast::visit::BoundKind; +use rustc_ast::visit::{BoundKind, Visitor}; use rustc_ast::{ self as ast, GenericArg, GenericBound, GenericParamKind, Generics, ItemKind, MetaItem, TraitBoundModifiers, VariantData, WherePredicate, }; use rustc_data_structures::flat_map_in_place::FlatMapInPlace; use rustc_errors::E0802; -use rustc_expand::base::{Annotatable, ExtCtxt}; +use rustc_expand::base::ExtCtxt; use rustc_macros::Diagnostic; use rustc_span::{Ident, Span, Symbol, sym}; use thin_vec::{ThinVec, thin_vec}; @@ -22,15 +22,13 @@ pub(crate) fn expand_deriving_coerce_pointee( cx: &ExtCtxt<'_>, span: Span, _mitem: &MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable), + item: &ast::Item, + push: &mut dyn FnMut(Box), _is_const: bool, ) { - item.visit_with(&mut DetectNonGenericPointeeAttr { cx }); + DetectNonGenericPointeeAttr { cx }.visit_item(item); - let (name_ident, generics) = if let Annotatable::Item(aitem) = item - && let ItemKind::Struct(ident, g, struct_data) = &aitem.kind - { + let (name_ident, generics) = if let ItemKind::Struct(ident, g, struct_data) = &item.kind { if !matches!( struct_data, VariantData::Struct { fields, recovered: _ } | VariantData::Tuple(fields, _) @@ -104,7 +102,7 @@ pub(crate) fn expand_deriving_coerce_pointee( let trait_path = cx.path_all(span, true, path!(span, core::marker::CoercePointeeValidated), vec![]); let trait_ref = cx.trait_ref(trait_path); - push(Annotatable::Item( + push( cx.item( span, attrs.clone(), @@ -144,7 +142,7 @@ pub(crate) fn expand_deriving_coerce_pointee( items: ThinVec::new(), }), ), - )); + ); } let mut add_impl_block = |generics, trait_symbol, trait_args| { let mut parts = path!(span, core::ops); @@ -167,7 +165,7 @@ pub(crate) fn expand_deriving_coerce_pointee( items: ThinVec::new(), }), ); - push(Annotatable::Item(item)); + push(item); }; // Create unsized `self`, that is, one where the `#[pointee]` type arg is replaced with `__S`. For diff --git a/compiler/rustc_builtin_macros/src/deriving/const_param_ty.rs b/compiler/rustc_builtin_macros/src/deriving/const_param_ty.rs new file mode 100644 index 0000000000000..18a9df86b547e --- /dev/null +++ b/compiler/rustc_builtin_macros/src/deriving/const_param_ty.rs @@ -0,0 +1,31 @@ +use rustc_ast::{MetaItem, Safety}; +use rustc_expand::base::ExtCtxt; +use rustc_span::Span; + +use crate::deriving::generic::*; +use crate::deriving::path_std; + +pub(crate) fn expand_deriving_const_param_ty( + cx: &ExtCtxt<'_>, + span: Span, + mitem: &MetaItem, + item: &ast::Item, + push: &mut dyn FnMut(Box), + is_const: bool, +) { + let trait_def = TraitDef { + span, + path: path_std!(marker::ConstParamTy_), + skip_path_as_bound: false, + needs_copy_as_bound_if_packed: false, + additional_bounds: smallvec![ty::Ty::Path(path_std!(cmp::Eq))], + supports_unions: false, + methods: SmallVec::new(), + associated_types: SmallVec::new(), + is_const, + safety: Safety::Default, + document: true, + }; + + trait_def.expand(cx, mitem, item, push); +} diff --git a/compiler/rustc_builtin_macros/src/deriving/copy.rs b/compiler/rustc_builtin_macros/src/deriving/copy.rs new file mode 100644 index 0000000000000..5743d27cf7458 --- /dev/null +++ b/compiler/rustc_builtin_macros/src/deriving/copy.rs @@ -0,0 +1,31 @@ +use rustc_ast::{MetaItem, Safety}; +use rustc_expand::base::ExtCtxt; +use rustc_span::Span; + +use crate::deriving::generic::*; +use crate::deriving::path_std; + +pub(crate) fn expand_deriving_copy( + cx: &ExtCtxt<'_>, + span: Span, + mitem: &MetaItem, + item: &ast::Item, + push: &mut dyn FnMut(Box), + is_const: bool, +) { + let trait_def = TraitDef { + span, + path: path_std!(marker::Copy), + skip_path_as_bound: false, + needs_copy_as_bound_if_packed: false, + additional_bounds: SmallVec::new(), + supports_unions: true, + methods: SmallVec::new(), + associated_types: SmallVec::new(), + is_const, + safety: Safety::Default, + document: true, + }; + + trait_def.expand(cx, mitem, item, push); +} diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index 94e0b704e6c08..3c80c01aa32b0 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -1,5 +1,5 @@ use rustc_ast::{self as ast, EnumDef, MetaItem, Safety}; -use rustc_expand::base::{Annotatable, ExtCtxt}; +use rustc_expand::base::ExtCtxt; use rustc_session::config::FmtDebug; use rustc_span::{Ident, Span, Symbol, sym}; use thin_vec::{ThinVec, thin_vec}; @@ -12,8 +12,8 @@ pub(crate) fn expand_deriving_debug( cx: &ExtCtxt<'_>, span: Span, mitem: &MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable), + item: &ast::Item, + push: &mut dyn FnMut(Box), is_const: bool, ) { // &mut ::std::fmt::Formatter diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index 3e4c5f1dcfa53..9e65ae0b75cab 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -1,8 +1,8 @@ use core::ops::ControlFlow; -use rustc_ast::visit::visit_opt; +use rustc_ast::visit::{Visitor, visit_opt}; use rustc_ast::{self as ast, EnumDef, Safety, VariantData, attr}; -use rustc_expand::base::{Annotatable, DummyResult, ExtCtxt}; +use rustc_expand::base::{DummyResult, ExtCtxt}; use rustc_span::{ErrorGuaranteed, Ident, Span, kw, sym}; use smallvec::SmallVec; use thin_vec::{ThinVec, thin_vec}; @@ -15,11 +15,11 @@ pub(crate) fn expand_deriving_default( cx: &ExtCtxt<'_>, span: Span, mitem: &ast::MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable), + item: &ast::Item, + push: &mut dyn FnMut(Box), is_const: bool, ) { - item.visit_with(&mut DetectNonVariantDefaultAttr { cx }); + DetectNonVariantDefaultAttr { cx }.visit_item(item); let trait_def = TraitDef { span, @@ -38,11 +38,11 @@ pub(crate) fn expand_deriving_default( fieldless_variants_strategy: FieldlessVariantsStrategy::Default, combine_substructure: combine_substructure(|cx, trait_span, substr| { match substr.fields { - StaticStruct(_, fields) => { - default_struct_substructure(cx, trait_span, substr, fields) + StaticStruct(variant_data) => { + default_struct_substructure(cx, trait_span, substr, variant_data) } StaticEnum(enum_def) => { - default_enum_substructure(cx, trait_span, enum_def, item.span()) + default_enum_substructure(cx, trait_span, enum_def, item.span) } _ => cx.dcx().span_bug(trait_span, "method in `derive(Default)`"), } @@ -66,27 +66,35 @@ fn default_struct_substructure( cx: &ExtCtxt<'_>, trait_span: Span, substr: &Substructure<'_>, - summary: &StaticFields<'_>, + variant_data: &VariantData, ) -> BlockOrExpr { - let expr = match summary { - Unnamed(_, IsTuple::No) => cx.expr_ident(trait_span, substr.type_ident), - Unnamed(fields, IsTuple::Yes) => { - let exprs = fields.iter().map(|sp| default_call(cx, *sp)).collect(); + let expr = match variant_data { + VariantData::Unit(_) => cx.expr_ident(trait_span, substr.type_ident), + VariantData::Tuple(fields, _) => { + let exprs = fields + .iter() + .map(|field| default_call(cx, field.span.with_ctxt(trait_span.ctxt()))) + .collect(); cx.expr_call_ident(trait_span, substr.type_ident, exprs) } - Named(fields) => { + VariantData::Struct { fields, .. } => { let default_fields = fields .iter() - .map(|&(ident, span, default_val)| { - let value = match default_val { - // We use `Default::default()`. - None => default_call(cx, span), + .map(|field| { + let span = field.span.with_ctxt(trait_span.ctxt()); + let value = if let Some(extras) = &field.extras + && let Some(default_val) = &extras.default + { // We use the field default const expression. - Some(val) => { - cx.expr(val.value.span, ast::ExprKind::ConstBlock(val.clone())) - } + cx.expr( + default_val.value.span, + ast::ExprKind::ConstBlock(default_val.clone()), + ) + } else { + // We use `Default::default()`. + default_call(cx, span) }; - cx.field_imm(span, ident, value) + cx.field_imm(span, field.ident.unwrap(), value) }) .collect(); cx.expr_struct_ident(trait_span, substr.type_ident, default_fields) @@ -308,7 +316,7 @@ impl<'a, 'b> rustc_ast::visit::Visitor<'a> for DetectNonVariantDefaultAttr<'a, ' } } -fn has_a_default_variant(item: &Annotatable) -> bool { +fn has_a_default_variant(item: &ast::Item) -> bool { struct HasDefaultAttrOnVariant; impl<'ast> rustc_ast::visit::Visitor<'ast> for HasDefaultAttrOnVariant { @@ -323,5 +331,5 @@ fn has_a_default_variant(item: &Annotatable) -> bool { } } - item.visit_with(&mut HasDefaultAttrOnVariant).is_break() + HasDefaultAttrOnVariant.visit_item(item).is_break() } diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs b/compiler/rustc_builtin_macros/src/deriving/eq.rs similarity index 96% rename from compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs rename to compiler/rustc_builtin_macros/src/deriving/eq.rs index 440360ca85d7d..8c160cb9868bf 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/eq.rs @@ -1,6 +1,6 @@ use rustc_ast::{self as ast, MetaItem, Safety}; use rustc_data_structures::fx::FxHashSet; -use rustc_expand::base::{Annotatable, ExtCtxt}; +use rustc_expand::base::ExtCtxt; use rustc_span::{Span, sym}; use thin_vec::{ThinVec, thin_vec}; @@ -12,8 +12,8 @@ pub(crate) fn expand_deriving_eq( cx: &ExtCtxt<'_>, span: Span, mitem: &MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable), + item: &ast::Item, + push: &mut dyn FnMut(Box), is_const: bool, ) { let span = cx.with_def_site_ctxt(span); diff --git a/compiler/rustc_builtin_macros/src/deriving/from.rs b/compiler/rustc_builtin_macros/src/deriving/from.rs index 9824ab5a225b7..eb8ddd10d4306 100644 --- a/compiler/rustc_builtin_macros/src/deriving/from.rs +++ b/compiler/rustc_builtin_macros/src/deriving/from.rs @@ -1,7 +1,7 @@ use rustc_ast as ast; use rustc_ast::{ItemKind, Safety, VariantData}; use rustc_errors::MultiSpan; -use rustc_expand::base::{Annotatable, DummyResult, ExtCtxt}; +use rustc_expand::base::{DummyResult, ExtCtxt}; use rustc_span::{Ident, Span, kw, sym}; use thin_vec::thin_vec; @@ -16,14 +16,10 @@ pub(crate) fn expand_deriving_from( cx: &ExtCtxt<'_>, span: Span, mitem: &ast::MetaItem, - annotatable: &Annotatable, - push: &mut dyn FnMut(Annotatable), + item: &ast::Item, + push: &mut dyn FnMut(Box), is_const: bool, ) { - let Annotatable::Item(item) = &annotatable else { - cx.dcx().bug("derive(From) used on something else than an item"); - }; - let err_span = || { let item_span = item.kind.ident().map(|ident| ident.span).unwrap_or(item.span); MultiSpan::from_spans(vec![span, item_span]) @@ -79,7 +75,7 @@ pub(crate) fn expand_deriving_from( supports_unions: false, methods: smallvec![MethodDef { name: sym::from, - generics: Bounds { bounds: vec![] }, + generics: Bounds::empty(), explicit_self: false, nonself_args: smallvec![(from_type, sym::value)], ret_ty: Ty::Self_, @@ -95,7 +91,7 @@ pub(crate) fn expand_deriving_from( let self_kw = Ident::new(kw::SelfUpper, span); let expr: Box = match substructure.fields { - SubstructureFields::StaticStruct(variant, _) => match variant { + SubstructureFields::StaticStruct(variant) => match variant { // Self { field: value } VariantData::Struct { .. } => cx.expr_struct_ident( span, @@ -127,5 +123,5 @@ pub(crate) fn expand_deriving_from( document: true, }; - from_trait_def.expand(cx, mitem, annotatable, push); + from_trait_def.expand(cx, mitem, item, push); } diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 6a53dafd396df..3298b4a583ff8 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -177,17 +177,17 @@ use std::ops::Not; use std::{iter, vec}; -pub(crate) use StaticFields::*; pub(crate) use SubstructureFields::*; +pub(crate) use rustc_ast as ast; use rustc_ast::token::{IdentIsRaw, LitKind, Token, TokenKind}; use rustc_ast::tokenstream::{DelimSpan, Spacing, TokenTree}; use rustc_ast::{ - self as ast, AnonConst, AttrArgs, BindingMode, ByRef, DelimArgs, EnumDef, Expr, GenericArg, - GenericParamKind, Generics, Mutability, PatKind, Safety, SelfKind, VariantData, + AttrArgs, BindingMode, ByRef, DelimArgs, EnumDef, Expr, GenericArg, GenericParamKind, Generics, + Mutability, PatKind, Safety, SelfKind, VariantData, }; use rustc_attr_ir::{Attribute, AttributeKind, ReprPacked}; use rustc_attr_parsing::AttributeParser; -use rustc_expand::base::{Annotatable, ExtCtxt}; +use rustc_expand::base::ExtCtxt; use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, respan, sym}; pub(crate) use smallvec::{SmallVec, smallvec}; use thin_vec::{ThinVec, thin_vec}; @@ -293,20 +293,6 @@ pub(crate) struct FieldInfo { pub maybe_scalar: bool, } -#[derive(Copy, Clone)] -pub(crate) enum IsTuple { - No, - Yes, -} - -/// Fields for a static method -pub(crate) enum StaticFields<'a> { - /// Tuple and unit structs/enum variants like this. - Unnamed(Vec, IsTuple), - /// Normal structs/struct variants. - Named(Vec<(Ident, Span, Option<&'a AnonConst>)>), -} - /// A summary of the possible sets of fields. pub(crate) enum SubstructureFields<'a> { /// A non-static method where `Self` is a struct. @@ -328,7 +314,7 @@ pub(crate) enum SubstructureFields<'a> { EnumDiscr(FieldInfo, Option>), /// A static method where `Self` is a struct. - StaticStruct(&'a ast::VariantData, StaticFields<'a>), + StaticStruct(&'a ast::VariantData), /// A static method where `Self` is an enum. StaticEnum(&'a ast::EnumDef), @@ -473,8 +459,8 @@ impl<'a> TraitDef<'a> { self, cx: &ExtCtxt<'_>, mitem: &ast::MetaItem, - item: &'a Annotatable, - push: &mut dyn FnMut(Annotatable), + item: &'a ast::Item, + push: &mut dyn FnMut(Box), ) { self.expand_ext(cx, mitem, item, push, false); } @@ -483,72 +469,62 @@ impl<'a> TraitDef<'a> { self, cx: &ExtCtxt<'_>, mitem: &ast::MetaItem, - item: &'a Annotatable, - push: &mut dyn FnMut(Annotatable), + item: &'a ast::Item, + push: &mut dyn FnMut(Box), from_scratch: bool, ) { - match item { - Annotatable::Item(item) => { - let is_packed = matches!( - AttributeParser::parse_limited_sym(cx.sess, &item.attrs, &[sym::repr]), - Some(Attribute::Parsed(AttributeKind::Repr { reprs, .. })) if reprs.iter().any(|(x, _)| matches!(x, ReprPacked(..))) - ); + let is_packed = matches!( + AttributeParser::parse_limited_sym(cx.sess, &item.attrs, &[sym::repr]), + Some(Attribute::Parsed(AttributeKind::Repr { reprs, .. })) if reprs.iter().any(|(x, _)| matches!(x, ReprPacked(..))) + ); - let mut newitem = match &item.kind { - ast::ItemKind::Struct(ident, generics, struct_def) => self.expand_struct_def( + let mut newitem = match &item.kind { + ast::ItemKind::Struct(ident, generics, struct_def) => { + self.expand_struct_def(cx, struct_def, *ident, generics, from_scratch, is_packed) + } + ast::ItemKind::Enum(ident, generics, enum_def) => { + // We ignore `is_packed` here, because `repr(packed)` + // enums cause an error later on. + // + // This can only cause further compilation errors + // downstream in blatantly illegal code, so it is fine. + self.expand_enum_def(cx, enum_def, *ident, generics, from_scratch) + } + ast::ItemKind::Union(ident, generics, struct_def) => { + if self.supports_unions { + self.expand_struct_def( cx, struct_def, *ident, generics, from_scratch, is_packed, - ), - ast::ItemKind::Enum(ident, generics, enum_def) => { - // We ignore `is_packed` here, because `repr(packed)` - // enums cause an error later on. - // - // This can only cause further compilation errors - // downstream in blatantly illegal code, so it is fine. - self.expand_enum_def(cx, enum_def, *ident, generics, from_scratch) - } - ast::ItemKind::Union(ident, generics, struct_def) => { - if self.supports_unions { - self.expand_struct_def( - cx, - struct_def, - *ident, - generics, - from_scratch, - is_packed, - ) - } else { - cx.dcx().emit_err(diagnostics::DeriveUnion { span: mitem.span }); - return; - } - } - _ => unreachable!(), - }; - // Keep the lint attributes of the previous item to control how the - // generated implementations are linted - newitem.attrs.extend( - item.attrs - .iter() - .filter(|a| { - a.has_any_name(&[ - sym::allow, - sym::warn, - sym::deny, - sym::forbid, - sym::stable, - sym::unstable, - ]) - }) - .cloned(), - ); - push(Annotatable::Item(newitem)) + ) + } else { + cx.dcx().emit_err(diagnostics::DeriveUnion { span: mitem.span }); + return; + } } _ => unreachable!(), - } + }; + // Keep the lint attributes of the previous item to control how the + // generated implementations are linted + newitem.attrs.extend( + item.attrs + .iter() + .filter(|a| { + a.has_any_name(&[ + sym::allow, + sym::warn, + sym::deny, + sym::forbid, + sym::stable, + sym::unstable, + ]) + }) + .cloned(), + ); + push(newitem); } /// Given that we are deriving a trait `DerivedTrait` for a type like: @@ -869,12 +845,12 @@ impl<'a> TraitDef<'a> { method_def.extract_arg_details(cx, self, type_ident, generics); let body = if from_scratch || method_def.is_static() { - method_def.expand_static_struct_method_body( + method_def.call_substructure_method( cx, self, - struct_def, type_ident, &nonselflike_args, + &StaticStruct(struct_def), ) } else { method_def.expand_struct_method_body( @@ -1142,25 +1118,6 @@ impl<'a> MethodDef<'a> { ) } - fn expand_static_struct_method_body( - &self, - cx: &ExtCtxt<'_>, - trait_: &TraitDef<'a>, - struct_def: &'a VariantData, - type_ident: Ident, - nonselflike_args: &[Box], - ) -> BlockOrExpr { - let summary = trait_.summarise_struct(cx, struct_def); - - self.call_substructure_method( - cx, - trait_, - type_ident, - nonselflike_args, - &StaticStruct(struct_def, summary), - ) - } - /// ``` /// #[derive(PartialEq)] /// # struct Dummy; @@ -1459,34 +1416,6 @@ impl<'a> MethodDef<'a> { // general helper methods. impl<'a> TraitDef<'a> { - fn summarise_struct(&self, cx: &ExtCtxt<'_>, struct_def: &'a VariantData) -> StaticFields<'a> { - let mut named_idents = Vec::new(); - let mut just_spans = Vec::new(); - for field in struct_def.fields() { - let sp = field.span.with_ctxt(self.span.ctxt()); - match field.ident { - Some(ident) => named_idents.push((ident, sp, field.default_value())), - _ => just_spans.push(sp), - } - } - - let is_tuple = match struct_def { - ast::VariantData::Tuple(..) => IsTuple::Yes, - _ => IsTuple::No, - }; - match (just_spans.is_empty(), named_idents.is_empty()) { - (false, false) => cx - .dcx() - .span_bug(self.span, "a struct with named and unnamed fields in generic `derive`"), - // named fields - (_, false) => Named(named_idents), - // unnamed fields - (false, _) => Unnamed(just_spans, is_tuple), - // empty - _ => Named(Vec::new()), - } - } - fn create_struct_patterns( &self, cx: &ExtCtxt<'_>, diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs index f1931aa90a435..6864b05ae08cd 100644 --- a/compiler/rustc_builtin_macros/src/deriving/hash.rs +++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs @@ -1,5 +1,5 @@ use rustc_ast::{MetaItem, Mutability, Safety}; -use rustc_expand::base::{Annotatable, ExtCtxt}; +use rustc_expand::base::ExtCtxt; use rustc_span::{Span, sym}; use thin_vec::thin_vec; @@ -11,8 +11,8 @@ pub(crate) fn expand_deriving_hash( cx: &ExtCtxt<'_>, span: Span, mitem: &MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable), + item: &ast::Item, + push: &mut dyn FnMut(Box), is_const: bool, ) { let path = path_std!(hash::Hash); diff --git a/compiler/rustc_builtin_macros/src/deriving/mod.rs b/compiler/rustc_builtin_macros/src/deriving/mod.rs index 602af919bd4f2..404991903c424 100644 --- a/compiler/rustc_builtin_macros/src/deriving/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/mod.rs @@ -14,28 +14,24 @@ macro path_std($($x:tt)*) { generic::ty::Path::new( pathvec!( $($x)* ) ) } -pub(crate) mod bounds; pub(crate) mod clone; pub(crate) mod coerce_pointee; +pub(crate) mod const_param_ty; +pub(crate) mod copy; pub(crate) mod debug; pub(crate) mod default; +pub(crate) mod eq; pub(crate) mod from; pub(crate) mod hash; -pub(crate) mod reborrow; - -#[path = "cmp/eq.rs"] -pub(crate) mod eq; -#[path = "cmp/ord.rs"] pub(crate) mod ord; -#[path = "cmp/partial_eq.rs"] pub(crate) mod partial_eq; -#[path = "cmp/partial_ord.rs"] pub(crate) mod partial_ord; +pub(crate) mod reborrow; pub(crate) mod generic; pub(crate) type BuiltinDeriveFn = - fn(&ExtCtxt<'_>, Span, &MetaItem, &Annotatable, &mut dyn FnMut(Annotatable), bool); + fn(&ExtCtxt<'_>, Span, &MetaItem, &ast::Item, &mut dyn FnMut(Box), bool); pub(crate) struct BuiltinDerive(pub(crate) BuiltinDeriveFn); @@ -59,25 +55,23 @@ impl MultiItemModifier for BuiltinDerive { ecx, span, meta_item, - &Annotatable::Item(item), - &mut |a| { - // Cannot use 'ecx.stmt_item' here, because we need to pass 'ecx' - // to the function - items.push(Annotatable::Stmt(Box::new(ast::Stmt { - id: ast::DUMMY_NODE_ID, - kind: ast::StmtKind::Item(a.expect_item()), - span, - }))); - }, + &item, + &mut |a| items.push(Annotatable::Stmt(Box::new(ecx.stmt_item(span, a)))), is_derive_const, ); } else { unreachable!("should have already errored on non-item statement") } } - _ => { - (self.0)(ecx, span, meta_item, &item, &mut |a| items.push(a), is_derive_const); - } + Annotatable::Item(item) => (self.0)( + ecx, + span, + meta_item, + &item, + &mut |a| items.push(Annotatable::Item(a)), + is_derive_const, + ), + _ => unreachable!(), } ExpandResult::Ready(items) } diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs b/compiler/rustc_builtin_macros/src/deriving/ord.rs similarity index 96% rename from compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs rename to compiler/rustc_builtin_macros/src/deriving/ord.rs index a1b38ceadb228..fb8d425841722 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/ord.rs @@ -1,5 +1,5 @@ use rustc_ast::{MetaItem, Safety}; -use rustc_expand::base::{Annotatable, ExtCtxt}; +use rustc_expand::base::ExtCtxt; use rustc_span::{Ident, Span, sym}; use thin_vec::thin_vec; @@ -11,8 +11,8 @@ pub(crate) fn expand_deriving_ord( cx: &ExtCtxt<'_>, span: Span, mitem: &MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable), + item: &ast::Item, + push: &mut dyn FnMut(Box), is_const: bool, ) { let trait_def = TraitDef { diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs b/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs similarity index 95% rename from compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs rename to compiler/rustc_builtin_macros/src/deriving/partial_eq.rs index b852e29b03ca4..a65962bfc9731 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs @@ -1,5 +1,5 @@ use rustc_ast::{BinOpKind, BorrowKind, Expr, ExprKind, MetaItem, Mutability, Safety}; -use rustc_expand::base::{Annotatable, ExtCtxt}; +use rustc_expand::base::ExtCtxt; use rustc_span::{Span, sym}; use thin_vec::thin_vec; @@ -13,8 +13,8 @@ pub(crate) fn expand_deriving_partial_eq( cx: &ExtCtxt<'_>, span: Span, mitem: &MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable), + item: &ast::Item, + push: &mut dyn FnMut(Box), is_const: bool, ) { let structural_trait_def = TraitDef { @@ -47,9 +47,7 @@ pub(crate) fn expand_deriving_partial_eq( ret_ty: Path(generic::ty::Path::new_local(sym::bool)), attributes: thin_vec![cx.attr_word(sym::inline, span)], fieldless_variants_strategy: FieldlessVariantsStrategy::Unify, - combine_substructure: combine_substructure(|a, b, c| { - BlockOrExpr::new_expr(get_substructure_equality_expr(a, b, c)) - }), + combine_substructure: combine_substructure(get_substructure_equality_expr), }]; let trait_def = TraitDef { @@ -123,10 +121,10 @@ fn get_substructure_equality_expr( cx: &ExtCtxt<'_>, span: Span, substructure: &Substructure<'_>, -) -> Box { +) -> BlockOrExpr { use SubstructureFields::*; - match substructure.fields { + BlockOrExpr::new_expr(match substructure.fields { EnumMatching(.., fields) | Struct(.., fields) => { let combine = move |acc, field| { let rhs = get_field_equality_expr(cx, field); @@ -151,7 +149,7 @@ fn get_substructure_equality_expr( EnumDiscr(disc, match_expr) => { let lhs = get_field_equality_expr(cx, disc); let Some(match_expr) = match_expr else { - return lhs; + return BlockOrExpr::new_expr(lhs); }; // Compare the discriminant first (cheaper), then the rest of the // fields. @@ -169,7 +167,7 @@ fn get_substructure_equality_expr( span, "unexpected all-fieldless enum encountered during `derive(PartialEq)` expansion", ), - } + }) } /// Generates an equality comparison expression for a single struct or enum diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs similarity index 84% rename from compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs rename to compiler/rustc_builtin_macros/src/deriving/partial_ord.rs index 88141224fddc2..0e547d441a74b 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs @@ -1,5 +1,5 @@ use rustc_ast::{ExprKind, ItemKind, MetaItem, PatKind, Safety, ast}; -use rustc_expand::base::{Annotatable, ExtCtxt}; +use rustc_expand::base::ExtCtxt; use rustc_span::{Ident, Span, sym}; use thin_vec::thin_vec; @@ -11,8 +11,8 @@ pub(crate) fn expand_deriving_partial_ord( cx: &ExtCtxt<'_>, span: Span, mitem: &MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable), + item: &ast::Item, + push: &mut dyn FnMut(Box), is_const: bool, ) { let ordering_ty = Path(path_std!(cmp::Ordering)); @@ -20,9 +20,7 @@ pub(crate) fn expand_deriving_partial_ord( Path(Path::new_(pathvec!(option::Option), vec![Box::new(ordering_ty)], PathKind::Std)); // Order in which to perform matching - let discr_then_data = if let Annotatable::Item(item) = item - && let ItemKind::Enum(_, _, def) = &item.kind - { + let discr_then_data = if let ItemKind::Enum(_, _, def) = &item.kind { let dataful: Vec = def.variants.iter().map(|v| !v.data.fields().is_empty()).collect(); match dataful.iter().filter(|&&b| b).count() { // No data, placing the discriminant check first makes codegen simpler @@ -49,29 +47,26 @@ pub(crate) fn expand_deriving_partial_ord( let simple_substructure = combine_substructure(|cx, span, _| { cs_partial_cmp_simple(cx, span, cx.expr_ident(span, Ident::new(sym::other, span))) }); - let is_simple = match item { - Annotatable::Item(annitem) => match &annitem.kind { - // For unit structs/zero-variant enums, the default generated code is better. - ItemKind::Struct(.., ast::VariantData::Unit(..)) => false, - // Also for single fieldless variant enum - ItemKind::Enum(.., enum_def) if enum_def.variants.is_empty() => false, - ItemKind::Enum(.., enum_def) - if enum_def.variants.len() == 1 - && matches!(enum_def.variants[0].data, ast::VariantData::Unit(..)) => - { - false - } - ItemKind::Struct(_, ast::Generics { params, .. }, _) - | ItemKind::Enum(_, ast::Generics { params, .. }, _) - if has_derive_ord - && !params - .iter() - .any(|param| matches!(param.kind, ast::GenericParamKind::Type { .. })) => - { - true - } - _ => false, - }, + let is_simple = match &item.kind { + // For unit structs/zero-variant enums, the default generated code is better. + ItemKind::Struct(.., ast::VariantData::Unit(..)) => false, + // Also for single fieldless variant enum + ItemKind::Enum(.., enum_def) if enum_def.variants.is_empty() => false, + ItemKind::Enum(.., enum_def) + if enum_def.variants.len() == 1 + && matches!(enum_def.variants[0].data, ast::VariantData::Unit(..)) => + { + false + } + ItemKind::Struct(_, ast::Generics { params, .. }, _) + | ItemKind::Enum(_, ast::Generics { params, .. }, _) + if has_derive_ord + && !params + .iter() + .any(|param| matches!(param.kind, ast::GenericParamKind::Type { .. })) => + { + true + } _ => false, }; diff --git a/compiler/rustc_builtin_macros/src/deriving/reborrow.rs b/compiler/rustc_builtin_macros/src/deriving/reborrow.rs index 9dc1ccf4fd8e6..43d24417acc00 100644 --- a/compiler/rustc_builtin_macros/src/deriving/reborrow.rs +++ b/compiler/rustc_builtin_macros/src/deriving/reborrow.rs @@ -2,7 +2,7 @@ use rustc_ast::{ self as ast, AttrArgs, GenericArg, GenericParamKind, Generics, ItemKind, MetaItem, token, }; use rustc_errors::E0802; -use rustc_expand::base::{Annotatable, ExtCtxt}; +use rustc_expand::base::ExtCtxt; use rustc_macros::Diagnostic; use rustc_span::{Ident, Span, Symbol, sym}; use thin_vec::ThinVec; @@ -15,8 +15,8 @@ pub(crate) fn expand_deriving_reborrow( cx: &ExtCtxt<'_>, span: Span, _mitem: &MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable), + item: &ast::Item, + push: &mut dyn FnMut(Box), _is_const: bool, ) { let Some((ident, generics)) = struct_def(cx, span, item, sym::Reborrow) else { @@ -30,8 +30,8 @@ pub(crate) fn expand_deriving_coerce_shared( cx: &ExtCtxt<'_>, span: Span, _mitem: &MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable), + item: &ast::Item, + push: &mut dyn FnMut(Box), _is_const: bool, ) { let Some((ident, generics)) = struct_def(cx, span, item, sym::CoerceShared) else { @@ -55,25 +55,19 @@ pub(crate) fn expand_deriving_coerce_shared( fn struct_def<'a>( cx: &ExtCtxt<'_>, span: Span, - item: &'a Annotatable, + item: &'a ast::Item, trait_name: Symbol, ) -> Option<(Ident, &'a Generics)> { - match item { - Annotatable::Item(item) => match &item.kind { - ItemKind::Struct(ident, generics, _) => Some((*ident, generics)), - ItemKind::Enum(..) => { - cx.dcx().emit_err(UnsupportedItem { span, trait_name, kind: "enum" }); - None - } - ItemKind::Union(..) => { - cx.dcx().emit_err(UnsupportedItem { span, trait_name, kind: "union" }); - None - } - _ => { - cx.dcx().emit_err(UnsupportedItem { span, trait_name, kind: "item" }); - None - } - }, + match &item.kind { + ItemKind::Struct(ident, generics, _) => Some((*ident, generics)), + ItemKind::Enum(..) => { + cx.dcx().emit_err(UnsupportedItem { span, trait_name, kind: "enum" }); + None + } + ItemKind::Union(..) => { + cx.dcx().emit_err(UnsupportedItem { span, trait_name, kind: "union" }); + None + } _ => { cx.dcx().emit_err(UnsupportedItem { span, trait_name, kind: "item" }); None @@ -81,12 +75,7 @@ fn struct_def<'a>( } } -fn coerce_shared_target(cx: &ExtCtxt<'_>, span: Span, item: &Annotatable) -> Option> { - let Annotatable::Item(item) = item else { - cx.dcx().emit_err(MissingTarget { span }); - return None; - }; - +fn coerce_shared_target(cx: &ExtCtxt<'_>, span: Span, item: &ast::Item) -> Option> { let mut attrs = item.attrs.iter().filter(|attr| attr.has_name(sym::coerce_shared)); let Some(attr) = attrs.next() else { cx.dcx().emit_err(MissingTarget { span }); @@ -130,7 +119,7 @@ fn push_marker_impl( generics: &Generics, trait_name: Symbol, trait_args: Vec, - push: &mut dyn FnMut(Annotatable), + push: &mut dyn FnMut(Box), ) { let mut trait_parts = path!(span, core::marker); trait_parts.push(Ident::new(trait_name, span)); @@ -154,7 +143,7 @@ fn push_marker_impl( .collect(); let self_ty = cx.ty_path(cx.path_all(span, false, vec![ident], self_params)); - push(Annotatable::Item(cx.item( + push(cx.item( span, thin_vec::thin_vec![cx.attr_word(sym::automatically_derived, span)], ast::ItemKind::Impl(ast::Impl { @@ -169,7 +158,7 @@ fn push_marker_impl( self_ty, items: ThinVec::new(), }), - ))); + )); } fn impl_generics(cx: &ExtCtxt<'_>, generics: &Generics) -> Generics { diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index db92413e1b162..57759bb113401 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -133,8 +133,8 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { register_derive! { Clone: clone::expand_deriving_clone, CoerceShared: reborrow::expand_deriving_coerce_shared, - Copy: bounds::expand_deriving_copy, - ConstParamTy: bounds::expand_deriving_const_param_ty, + Copy: copy::expand_deriving_copy, + ConstParamTy: const_param_ty::expand_deriving_const_param_ty, Debug: debug::expand_deriving_debug, Default: default::expand_deriving_default, Eq: eq::expand_deriving_eq, diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index 88049d67964b1..83f2bcdd3959c 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -18,7 +18,7 @@ use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::traits::{ BackendTypes, BaseTypeCodegenMethods, BuilderMethods, ConstCodegenMethods, - LayoutTypeCodegenMethods, OverflowOp, StaticBuilderMethods, + LayoutTypeCodegenMethods, OverflowOp, ReturnSlot, StaticBuilderMethods, }; use rustc_data_structures::fx::FxHashSet; use rustc_middle::bug; @@ -608,6 +608,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { fn_attrs: Option<&CodegenFnAttrs>, fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, func: RValue<'gcc>, + return_slot: ReturnSlot>, args: &[RValue<'gcc>], then: Block<'gcc>, catch: Block<'gcc>, @@ -618,7 +619,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let current_block = self.block; self.block = try_block; - let call = self.call(typ, fn_attrs, fn_abi, func, args, None, instance); // FIXME(antoyo): use funclet here? + // FIXME(antoyo): use funclet here? + let call = self.call(typ, fn_attrs, fn_abi, func, return_slot, args, None, instance); self.block = current_block; let return_value = @@ -646,13 +648,14 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { fn_attrs: Option<&CodegenFnAttrs>, fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, func: RValue<'gcc>, + return_slot: ReturnSlot>, args: &[RValue<'gcc>], then: Block<'gcc>, catch: Block<'gcc>, _funclet: Option<&Funclet>, instance: Option>, ) -> RValue<'gcc> { - let call_site = self.call(typ, fn_attrs, fn_abi, func, args, None, instance); + let call_site = self.call(typ, fn_attrs, fn_abi, func, return_slot, args, None, instance); let condition = self.context.new_rvalue_from_int(self.bool_type, 1); self.llbb().end_with_conditional(self.location, condition, then, catch); if let Some(_fn_abi) = fn_abi { @@ -1779,19 +1782,30 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { _fn_attrs: Option<&CodegenFnAttrs>, fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, func: RValue<'gcc>, + return_slot: ReturnSlot>, args: &[RValue<'gcc>], funclet: Option<&Funclet>, _instance: Option>, ) -> RValue<'gcc> { + // FIXME: change this in the `rustc_codegen_gcc` repo after the sync, to use the `libgccjit` indirect return suppport. + let args = match return_slot { + ReturnSlot::Direct => args.to_vec(), + ReturnSlot::Indirect(sret_ptr) => { + let mut args = args.to_vec(); + // Prepend the indirect return pointer + args.insert(0, sret_ptr); + args + } + }; // FIXME(antoyo): remove when having a proper API. let gcc_func = unsafe { std::mem::transmute::, Function<'gcc>>(func) }; let call = if self.functions.borrow().values().any(|value| *value == gcc_func) { // FIXME(antoyo): remove when the API supports a different type for functions. let func: Function<'gcc> = self.cx.rvalue_as_function(func); - self.function_call(func, args, funclet) + self.function_call(func, &args, funclet) } else { // If it's a not function that was defined, it's a function pointer. - self.function_ptr_call(typ, fn_abi, func, args, funclet) + self.function_ptr_call(typ, fn_abi, func, &args, funclet) }; if let Some(_fn_abi) = fn_abi { // FIXME(bjorn3): Apply function attributes @@ -1805,6 +1819,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { _fn_attrs: Option<&CodegenFnAttrs>, _fn_abi: &FnAbi<'tcx, Ty<'tcx>>, _llfn: Self::Value, + _return_slot: ReturnSlot, _args: &[Self::Value], _funclet: Option<&Self::Funclet>, _instance: Option>, diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index 5550d22b33aa3..06713016cedbe 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -16,7 +16,7 @@ use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue}; use rustc_codegen_ssa::traits::MiscCodegenMethods; use rustc_codegen_ssa::traits::{ ArgAbiBuilderMethods, BaseTypeCodegenMethods, BuilderMethods, ConstCodegenMethods, - IntrinsicCallBuilderMethods, LayoutTypeCodegenMethods, + IntrinsicCallBuilderMethods, LayoutTypeCodegenMethods, ReturnSlot, }; use rustc_codegen_ssa::{MemFlags, RetagInfo}; use rustc_data_structures::fx::FxHashSet; @@ -655,7 +655,8 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc } // FIXME directly use the llvm intrinsic adjustment functions here - let llret = self.call(fn_ty, None, None, fn_ptr, &call_args, None, None); + let llret = + self.call(fn_ty, None, None, fn_ptr, ReturnSlot::Direct, &call_args, None, None); if is_cleanup { self.apply_attrs_to_cleanup_callsite(llret); } @@ -666,7 +667,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc fn abort(&mut self) { let func = self.context.get_builtin_function("abort"); let func: RValue<'gcc> = unsafe { std::mem::transmute(func) }; - self.call(self.type_void(), None, None, func, &[], None, None); + self.call(self.type_void(), None, None, func, ReturnSlot::Direct, &[], None, None); } fn assume(&mut self, value: Self::Value) { @@ -1347,7 +1348,7 @@ fn try_intrinsic<'a, 'b, 'gcc, 'tcx>( let param_type = bx.u8_type.make_pointer(); let fn_type = bx.context.new_function_pointer_type(None, bx.type_void(), &[param_type], false); - bx.call(fn_type, None, None, try_func, &[data], None, None); + bx.call(fn_type, None, None, try_func, ReturnSlot::Direct, &[data], None, None); // Return 0 unconditionally from the intrinsic call; // we can never unwind. OperandValue::Immediate(bx.const_bool(false)).store(bx, dest); @@ -1420,21 +1421,41 @@ fn codegen_gnu_try<'gcc, 'tcx>( let zero = bx.cx.context.new_rvalue_zero(bx.int_type); let ptr = bx.cx.context.new_call(None, eh_pointer_builtin, &[zero]); let catch_ty = bx.type_func(&[bx.type_i8p(), bx.type_i8p()], bx.type_void()); - bx.call(catch_ty, None, None, catch_func, &[data, ptr], None, None); + bx.call(catch_ty, None, None, catch_func, ReturnSlot::Direct, &[data, ptr], None, None); bx.ret(bx.const_bool(true)); // NOTE: the blocks must be filled before adding the try/catch, otherwise gcc will not // generate a try/catch. // FIXME(antoyo): add a check in the libgccjit API to prevent this. bx.switch_to_block(current_block); - bx.invoke(try_func_ty, None, None, try_func, &[data], then, catch, None, None); + bx.invoke( + try_func_ty, + None, + None, + try_func, + ReturnSlot::Direct, + &[data], + then, + catch, + None, + None, + ); }); let func = unsafe { std::mem::transmute::, RValue<'gcc>>(func) }; // Note that no invoke is used here because by definition this function // can't panic (that's what it's catching). - let ret = bx.call(llty, None, None, func, &[try_func, data, catch_func], None, None); + let ret = bx.call( + llty, + None, + None, + func, + ReturnSlot::Direct, + &[try_func, data, catch_func], + None, + None, + ); OperandValue::Immediate(ret).store(bx, dest); } diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index c22318c0ec8a7..8e5750a2998bc 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -586,9 +586,20 @@ pub(crate) fn inline_asm_call<'ll>( assert!(catch_funclet.is_none()); bx.callbr(fty, None, None, v, inputs, dest.unwrap(), labels, None, None) } else if let Some((catch, funclet)) = catch_funclet { - bx.invoke(fty, None, None, v, inputs, dest.unwrap(), catch, funclet, None) + bx.invoke( + fty, + None, + None, + v, + ReturnSlot::Direct, + inputs, + dest.unwrap(), + catch, + funclet, + None, + ) } else { - bx.call(fty, None, None, v, inputs, None, None) + bx.call(fty, None, None, v, ReturnSlot::Direct, inputs, None, None) }; // Store mark in a metadata node so we can map LLVM errors diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index dae8b2d17e0e1..9d4602e49968d 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -454,15 +454,25 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn_attrs: Option<&CodegenFnAttrs>, fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, llfn: &'ll Value, + return_slot: ReturnSlot<&'ll Value>, args: &[&'ll Value], then: &'ll BasicBlock, catch: &'ll BasicBlock, funclet: Option<&Funclet<'ll>>, instance: Option>, ) -> &'ll Value { + // If this function returns indirectly (`PassMode::Indirect`), + // the `return_slot` should be the first argument. + let args = match return_slot { + ReturnSlot::Direct => args.to_vec(), + ReturnSlot::Indirect(sret_ptr) => { + let mut args = args.to_vec(); + args.insert(0, sret_ptr); + args + } + }; debug!("invoke {:?} with args ({:?})", llfn, args); - - let args = self.check_call("invoke", llty, llfn, args); + let args = self.check_call("invoke", llty, llfn, &args); let funclet_bundle = funclet.map(|funclet| funclet.bundle()); let mut bundles: SmallVec<[_; 2]> = SmallVec::new(); if let Some(funclet_bundle) = funclet_bundle { @@ -1463,13 +1473,23 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { caller_attrs: Option<&CodegenFnAttrs>, fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, llfn: &'ll Value, + return_slot: ReturnSlot<&'ll Value>, args: &[&'ll Value], funclet: Option<&Funclet<'ll>>, callee_instance: Option>, ) -> &'ll Value { + // If this function returns indirectly (`PassMode::Indirect`), + // the `return_slot` should be the first argument. + let args = match return_slot { + ReturnSlot::Direct => args.to_vec(), + ReturnSlot::Indirect(sret_ptr) => { + let mut args = args.to_vec(); + args.insert(0, sret_ptr); + args + } + }; debug!("call {:?} with args ({:?})", llfn, args); - - let args = self.check_call("call", llty, llfn, args); + let args = self.check_call("call", llty, llfn, &args); let funclet_bundle = funclet.map(|funclet| funclet.bundle()); let mut bundles: SmallVec<[_; 2]> = SmallVec::new(); if let Some(funclet_bundle) = funclet_bundle { @@ -1530,12 +1550,21 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { caller_attrs: Option<&CodegenFnAttrs>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, llfn: Self::Value, + return_slot: ReturnSlot, args: &[Self::Value], funclet: Option<&Self::Funclet>, callee_instance: Option>, ) { - let call = - self.call(llty, caller_attrs, Some(fn_abi), llfn, args, funclet, callee_instance); + let call = self.call( + llty, + caller_attrs, + Some(fn_abi), + llfn, + return_slot, + args, + funclet, + callee_instance, + ); llvm::LLVMSetTailCallKind(call, llvm::TailCallKind::MustTail); match &fn_abi.ret.mode { @@ -1875,7 +1904,8 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { args: &[&'ll Value], ) -> &'ll Value { let (ty, f) = self.cx.get_intrinsic(base_name.into(), type_params); - self.call(ty, None, None, f, args, None, None) + // No LLVM intrinsic returns its data indirectly (via `sret`). + self.call(ty, None, None, f, ReturnSlot::Direct, args, None, None) } fn call_lifetime_intrinsic(&mut self, intrinsic: &'static str, ptr: &'ll Value, size: Size) { @@ -2091,6 +2121,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { None, None, ubsan_handler, + ReturnSlot::Direct, &[diag_data, function_address, self.const_usize(0)], None, None, diff --git a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs index 8cefd8dc489a9..3831f3b0912fd 100644 --- a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs +++ b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs @@ -6,7 +6,7 @@ use rustc_codegen_ssa::common::TypeKind; use rustc_codegen_ssa::mir::IntrinsicResult; use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; use rustc_codegen_ssa::mir::place::PlaceValue; -use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods}; +use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods, ReturnSlot}; use rustc_data_structures::thin_vec::ThinVec; use rustc_hir::attrs::RustcAutodiff; use rustc_middle::ty::{PseudoCanonicalInput, Ty, TyCtxt, TypingEnv}; @@ -372,7 +372,7 @@ pub(crate) fn generate_enzyme_call<'ll, 'tcx>( crate::typetree::add_tt(&bx, fn_to_diff, fnc_tree); } - let call = bx.call(enzyme_ty, None, None, ad_fn, &args, None, None); + let call = bx.call(enzyme_ty, None, None, ad_fn, ReturnSlot::Direct, &args, None, None); let fn_ret_ty = bx.cx.val_ty(call); if fn_ret_ty == bx.cx.type_void() || fn_ret_ty == bx.cx.type_struct(&[], false) { diff --git a/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs b/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs index e2ec20226e3ce..a84ca02cc3b18 100644 --- a/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs +++ b/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs @@ -6,7 +6,7 @@ use rustc_abi::Align; use rustc_codegen_ssa::MemFlags; use rustc_codegen_ssa::common::TypeKind; use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; -use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods}; +use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods, ReturnSlot}; use rustc_middle::bug; use rustc_middle::ty::offload_meta::{MappingFlags, OffloadMetadata, OffloadSize}; @@ -681,7 +681,7 @@ pub(crate) fn gen_call_handling<'ll, 'tcx>( let num_args = cx.get_const_i32(num_args); let args = vec![s_ident_t, i64_max, num_args, geps[0], geps[1], geps[2], o_type, nullptr, nullptr]; - builder.call(fn_ty, None, None, fn_to_call, &args, None, None); + builder.call(fn_ty, None, None, fn_to_call, ReturnSlot::Direct, &args, None, None); } // Step 2) @@ -718,7 +718,7 @@ pub(crate) fn gen_call_handling<'ll, 'tcx>( let device_id = builder.sext(device_id, cx.type_i64()); let args = vec![s_ident_t, device_id, num_workgroups, threads_per_block, region_id, a5]; - builder.call(tgt_target_kernel_ty, None, None, tgt_decl, &args, None, None); + builder.call(tgt_target_kernel_ty, None, None, tgt_decl, ReturnSlot::Direct, &args, None, None); // %41 = call i32 @__tgt_target_kernel(ptr @1, i64 -1, i32 2097152, i32 256, ptr @.kernel_1.region_id, ptr %kernel_args) // Step 4) diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 743145a0e5baf..f3740ed7504fe 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -245,7 +245,8 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { sym::offload_get_num_devices => { let (fn_decl, fn_ty) = declare_omp_get_num_devices(self.cx); - let llval = self.call(fn_ty, None, None, fn_decl, &[], None, None); + let llval = + self.call(fn_ty, None, None, fn_decl, ReturnSlot::Direct, &[], None, None); return IntrinsicResult::Operand(OperandValue::Immediate(llval)); } @@ -1354,7 +1355,7 @@ fn catch_unwind_intrinsic<'ll, 'tcx>( ) -> &'ll Value { if !bx.sess().panic_strategy().unwinds() { let try_func_ty = bx.type_func(&[bx.type_ptr()], bx.type_void()); - bx.call(try_func_ty, None, None, try_func, &[data], None, None); + bx.call(try_func_ty, None, None, try_func, ReturnSlot::Direct, &[data], None, None); // Return 0 unconditionally from the intrinsic call; // we can never unwind. bx.const_bool(false) @@ -1452,7 +1453,18 @@ fn codegen_msvc_try<'ll, 'tcx>( let ptr_align = bx.tcx().data_layout.pointer_align().abi; let slot = bx.alloca(ptr_size, ptr_align); let try_func_ty = bx.type_func(&[bx.type_ptr()], bx.type_void()); - bx.invoke(try_func_ty, None, None, try_func, &[data], normal, catchswitch, None, None); + bx.invoke( + try_func_ty, + None, + None, + try_func, + ReturnSlot::Direct, + &[data], + normal, + catchswitch, + None, + None, + ); bx.switch_to_block(normal); bx.ret(bx.const_bool(false)); @@ -1500,7 +1512,16 @@ fn codegen_msvc_try<'ll, 'tcx>( let funclet = bx.catch_pad(cs, &[tydesc, flags, slot]); let ptr = bx.load(bx.type_ptr(), slot, ptr_align); let catch_ty = bx.type_func(&[bx.type_ptr(), bx.type_ptr()], bx.type_void()); - bx.call(catch_ty, None, None, catch_func, &[data, ptr], Some(&funclet), None); + bx.call( + catch_ty, + None, + None, + catch_func, + ReturnSlot::Direct, + &[data, ptr], + Some(&funclet), + None, + ); bx.catch_ret(&funclet, caught); // The flag value of 64 indicates a "catch-all". @@ -1508,7 +1529,16 @@ fn codegen_msvc_try<'ll, 'tcx>( let flags = bx.const_i32(64); let null = bx.const_null(bx.type_ptr()); let funclet = bx.catch_pad(cs, &[null, flags, null]); - bx.call(catch_ty, None, None, catch_func, &[data, null], Some(&funclet), None); + bx.call( + catch_ty, + None, + None, + catch_func, + ReturnSlot::Direct, + &[data, null], + Some(&funclet), + None, + ); bx.catch_ret(&funclet, caught); bx.switch_to_block(caught); @@ -1517,7 +1547,16 @@ fn codegen_msvc_try<'ll, 'tcx>( // Note that no invoke is used here because by definition this function // can't panic (that's what it's catching). - let ret = bx.call(llty, None, None, llfn, &[try_func, data, catch_func], None, None); + let ret = bx.call( + llty, + None, + None, + llfn, + ReturnSlot::Direct, + &[try_func, data, catch_func], + None, + None, + ); ret } @@ -1564,7 +1603,18 @@ fn codegen_wasm_try<'ll, 'tcx>( // } // let try_func_ty = bx.type_func(&[bx.type_ptr()], bx.type_void()); - bx.invoke(try_func_ty, None, None, try_func, &[data], normal, catchswitch, None, None); + bx.invoke( + try_func_ty, + None, + None, + try_func, + ReturnSlot::Direct, + &[data], + normal, + catchswitch, + None, + None, + ); bx.switch_to_block(normal); bx.ret(bx.const_bool(false)); @@ -1580,7 +1630,16 @@ fn codegen_wasm_try<'ll, 'tcx>( let _sel = bx.call_intrinsic("llvm.wasm.get.ehselector", &[], &[funclet.cleanuppad()]); let catch_ty = bx.type_func(&[bx.type_ptr(), bx.type_ptr()], bx.type_void()); - bx.call(catch_ty, None, None, catch_func, &[data, ptr], Some(&funclet), None); + bx.call( + catch_ty, + None, + None, + catch_func, + ReturnSlot::Direct, + &[data, ptr], + Some(&funclet), + None, + ); bx.catch_ret(&funclet, caught); bx.switch_to_block(caught); @@ -1589,7 +1648,16 @@ fn codegen_wasm_try<'ll, 'tcx>( // Note that no invoke is used here because by definition this function // can't panic (that's what it's catching). - let ret = bx.call(llty, None, None, llfn, &[try_func, data, catch_func], None, None); + let ret = bx.call( + llty, + None, + None, + llfn, + ReturnSlot::Direct, + &[try_func, data, catch_func], + None, + None, + ); ret } @@ -1630,7 +1698,18 @@ fn codegen_gnu_try<'ll, 'tcx>( let data = llvm::get_param(bx.llfn(), 1); let catch_func = llvm::get_param(bx.llfn(), 2); let try_func_ty = bx.type_func(&[bx.type_ptr()], bx.type_void()); - bx.invoke(try_func_ty, None, None, try_func, &[data], then, catch, None, None); + bx.invoke( + try_func_ty, + None, + None, + try_func, + ReturnSlot::Direct, + &[data], + then, + catch, + None, + None, + ); bx.switch_to_block(then); bx.ret(bx.const_bool(false)); @@ -1648,13 +1727,22 @@ fn codegen_gnu_try<'ll, 'tcx>( bx.add_clause(vals, tydesc); let ptr = bx.extract_value(vals, 0); let catch_ty = bx.type_func(&[bx.type_ptr(), bx.type_ptr()], bx.type_void()); - bx.call(catch_ty, None, None, catch_func, &[data, ptr], None, None); + bx.call(catch_ty, None, None, catch_func, ReturnSlot::Direct, &[data, ptr], None, None); bx.ret(bx.const_bool(true)); }); // Note that no invoke is used here because by definition this function // can't panic (that's what it's catching). - let ret = bx.call(llty, None, None, llfn, &[try_func, data, catch_func], None, None); + let ret = bx.call( + llty, + None, + None, + llfn, + ReturnSlot::Direct, + &[try_func, data, catch_func], + None, + None, + ); ret } diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs index d67156c6cfa39..e0b1df0bb632c 100644 --- a/compiler/rustc_codegen_llvm/src/mono_item.rs +++ b/compiler/rustc_codegen_llvm/src/mono_item.rs @@ -198,12 +198,21 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { args.push(llvm::get_param(alias_lldecl, index)); } + // For an indirect return, the alias's own first parameter is the + // caller-provided return slot: forward it to the aliasee as such. + let (return_slot, args) = if fn_abi.ret.is_indirect() { + let (sret_ptr, rest) = args.split_first().unwrap(); + (ReturnSlot::Indirect(*sret_ptr), rest) + } else { + (ReturnSlot::Direct, &args[..]) + }; let call = start_bx.call( fn_ty, Some(attrs), Some(fn_abi), aliasee, - &args, + return_slot, + args, None, Some(aliasee_instance), ); diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 8dd129f45cc5a..d909316194566 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -593,7 +593,8 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( ) }; - let result = bx.call(start_ty, None, None, start_fn, &args, None, instance); + let result = + bx.call(start_ty, None, None, start_fn, ReturnSlot::Direct, &args, None, instance); if cx.sess().target.os == Os::Uefi { bx.ret(result); } else { diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index afd9a88784c2f..c3d66b6df2b81 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -165,12 +165,16 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { /// Call `fn_ptr` of `fn_abi` with the arguments `llargs`, the optional /// return destination `destination` and the unwind action `unwind`. + /// The `return_slot` is [`ReturnSlot::Indirect`] for functions returning + /// via `PassMode::Indirect`, and points to a buffer where the return value + /// shall be stored. fn do_call>( &self, fx: &mut FunctionCx<'a, 'tcx, Bx>, bx: &mut Bx, fn_abi: &'tcx FnAbi<'tcx, Ty<'tcx>>, fn_ptr: Bx::Value, + return_slot: ReturnSlot, llargs: &[Bx::Value], destination: Option<(ReturnDest<'tcx, Bx::Value>, mir::BasicBlock)>, mut unwind: mir::UnwindAction, @@ -244,8 +248,23 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { } }; + debug_assert_eq!( + return_slot.is_indirect(), + fn_abi.ret.is_indirect(), + "a return slot must be provided if and only if the return is `PassMode::Indirect`", + ); + if kind == CallKind::Tail { - bx.tail_call(fn_ty, caller_attrs, fn_abi, fn_ptr, llargs, self.funclet(fx), instance); + bx.tail_call( + fn_ty, + caller_attrs, + fn_abi, + fn_ptr, + return_slot, + llargs, + self.funclet(fx), + instance, + ); return MergingSucc::False; } @@ -260,6 +279,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { caller_attrs, Some(fn_abi), fn_ptr, + return_slot, llargs, ret_llbb, unwind_block, @@ -291,6 +311,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { caller_attrs, Some(fn_abi), fn_ptr, + return_slot, llargs, self.funclet(fx), instance, @@ -718,6 +739,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx, fn_abi, drop_fn, + ReturnSlot::Direct, args, Some((ReturnDest::Nothing, target)), unwind, @@ -822,6 +844,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx, fn_abi, llfn, + ReturnSlot::Direct, &args, None, unwind, @@ -853,6 +876,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx, fn_abi, llfn, + ReturnSlot::Direct, &[], None, mir::UnwindAction::Unreachable, @@ -922,6 +946,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx, fn_abi, llfn, + ReturnSlot::Direct, &[msg.0, msg.1], target.as_ref().map(|bb| (ReturnDest::Nothing, *bb)), unwind, @@ -1202,21 +1227,24 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // We still need to call `make_return_dest` even if there's no `target`, since // `fn_abi.ret` could be `PassMode::Indirect`, even if it is uninhabited, // and `make_return_dest` adds the return-place indirect pointer to `llargs`. - let destination = match kind { + let (destination, return_slot) = match kind { CallKind::Normal => { - let return_dest = self.make_return_dest(bx, destination, &fn_abi.ret, &mut llargs); - target.map(|target| (return_dest, target)) + let (return_dest, return_slot) = + self.make_return_dest(bx, destination, &fn_abi.ret); + (target.map(|target| (return_dest, target)), return_slot) } CallKind::Tail => { - if fn_abi.ret.is_indirect() { - match self.make_return_dest(bx, destination, &fn_abi.ret, &mut llargs) { - ReturnDest::Nothing => {} + let return_slot = if fn_abi.ret.is_indirect() { + match self.make_return_dest(bx, destination, &fn_abi.ret) { + (ReturnDest::Nothing, return_slot) => return_slot, _ => bug!( "tail calls to functions with indirect returns cannot store into a destination" ), } - } - None + } else { + ReturnSlot::Direct + }; + (None, return_slot) } }; @@ -1441,6 +1469,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx, fn_abi, fn_ptr, + return_slot, &llargs, destination, unwind, @@ -2360,7 +2389,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } else { let fn_ty = bx.fn_decl_backend_type(fn_abi); - let llret = bx.call(fn_ty, None, Some(fn_abi), fn_ptr, &[], funclet.as_ref(), None); + let llret = bx.call( + fn_ty, + None, + Some(fn_abi), + fn_ptr, + ReturnSlot::Direct, + &[], + funclet.as_ref(), + None, + ); bx.apply_attrs_to_cleanup_callsite(llret); } @@ -2396,11 +2434,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx: &mut Bx, dest: mir::Place<'tcx>, fn_ret: &ArgAbi<'tcx, Ty<'tcx>>, - llargs: &mut Vec, - ) -> ReturnDest<'tcx, Bx::Value> { + ) -> (ReturnDest<'tcx, Bx::Value>, ReturnSlot) { // If the return is ignored, we can just return a do-nothing `ReturnDest`. if fn_ret.is_ignore() { - return ReturnDest::Nothing; + return (ReturnDest::Nothing, ReturnSlot::Direct); } let dest = if let Some(index) = dest.as_local() { match self.locals[index] { @@ -2414,10 +2451,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // but the calling convention has an indirect return. let tmp = PlaceRef::alloca(bx, fn_ret.layout); tmp.storage_live(bx); - llargs.push(tmp.val.llval); - ReturnDest::IndirectOperand(tmp, index) + ( + ReturnDest::IndirectOperand(tmp, index), + ReturnSlot::Indirect(tmp.val.llval), + ) } else { - ReturnDest::DirectOperand(index) + (ReturnDest::DirectOperand(index), ReturnSlot::Direct) }; } LocalRef::Operand(_) => { @@ -2437,10 +2476,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // to create a temporary. span_bug!(self.mir.span, "can't directly store to unaligned value"); } - llargs.push(dest.val.llval); - ReturnDest::Nothing + (ReturnDest::Nothing, ReturnSlot::Indirect(dest.val.llval)) } else { - ReturnDest::Store(dest) + (ReturnDest::Store(dest), ReturnSlot::Direct) } } diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 344a4834862e4..6278020eabecd 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -779,6 +779,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { fn_attrs.as_deref(), Some(fn_abi), fn_ptr, + ReturnSlot::Direct, &[], None, Some(instance), diff --git a/compiler/rustc_codegen_ssa/src/size_of_val.rs b/compiler/rustc_codegen_ssa/src/size_of_val.rs index 0ef0179eac6c4..e286681c293ee 100644 --- a/compiler/rustc_codegen_ssa/src/size_of_val.rs +++ b/compiler/rustc_codegen_ssa/src/size_of_val.rs @@ -78,6 +78,7 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( /* fn_attrs */ None, Some(fn_abi), llfn, + ReturnSlot::Direct, // we know the ABI here &[msg.0, msg.1], None, None, diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index cb0209a0ae369..b7b694922bcfa 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -34,6 +34,20 @@ pub enum OverflowOp { Mul, } +/// The location of the return value for the call. +#[derive(Copy, Clone, Debug)] +pub enum ReturnSlot { + Direct, + /// The return value will be passed via sret (e.g. `PassMode::Indirect`). + Indirect(V), +} + +impl ReturnSlot { + pub fn is_indirect(&self) -> bool { + matches!(self, ReturnSlot::Indirect(_)) + } +} + pub trait BuilderMethods<'a, 'tcx>: Sized + LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>> @@ -135,6 +149,7 @@ pub trait BuilderMethods<'a, 'tcx>: fn_attrs: Option<&CodegenFnAttrs>, fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, llfn: Self::Value, + return_slot: ReturnSlot, args: &[Self::Value], then: Self::BasicBlock, catch: Self::BasicBlock, @@ -638,16 +653,20 @@ pub trait BuilderMethods<'a, 'tcx>: /// The typical case that they are None is during the codegen of intrinsics and lang-items, /// as those are "fake functions" with only a trivial ABI if any, et cetera. /// + /// `return_slot` must be `ReturnSlot::Indirect` if an argument uses `PassMode::Indirect`. + /// /// ## Return /// - /// Must return the value the function will return so it can be written to the destination, - /// assuming the function does not explicitly pass the destination as a pointer in `args`. + /// Must return the value the function will return so it can be written to the destination. + /// For calls with an indirect return, the returned value is meaningless and must not be + /// used: the return value lives in the return slot. fn call( &mut self, llty: Self::FunctionSignature, caller_attrs: Option<&CodegenFnAttrs>, fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, fn_val: Self::Value, + return_slot: ReturnSlot, args: &[Self::Value], funclet: Option<&Self::Funclet>, callee_instance: Option>, @@ -659,6 +678,7 @@ pub trait BuilderMethods<'a, 'tcx>: caller_attrs: Option<&CodegenFnAttrs>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, llfn: Self::Value, + return_slot: ReturnSlot, args: &[Self::Value], funclet: Option<&Self::Funclet>, callee_instance: Option>, diff --git a/compiler/rustc_codegen_ssa/src/traits/mod.rs b/compiler/rustc_codegen_ssa/src/traits/mod.rs index f46d07ea5008e..1f013cb122070 100644 --- a/compiler/rustc_codegen_ssa/src/traits/mod.rs +++ b/compiler/rustc_codegen_ssa/src/traits/mod.rs @@ -36,7 +36,7 @@ pub use self::asm::{ AsmBuilderMethods, AsmCodegenMethods, GlobalAsmOperandRef, InlineAsmOperandRef, }; pub use self::backend::{BackendTypes, CodegenBackend, ExtraBackendMethods}; -pub use self::builder::{BuilderMethods, OverflowOp}; +pub use self::builder::{BuilderMethods, OverflowOp, ReturnSlot}; pub use self::consts::ConstCodegenMethods; pub use self::coverageinfo::CoverageInfoBuilderMethods; pub use self::debuginfo::{DebugInfoBuilderMethods, DebugInfoCodegenMethods}; diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 7efa784bd8622..c72a89ccdee76 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -605,6 +605,9 @@ declare_features! ( (unstable, macro_metavar_expr, "1.61.0", Some(83527)), /// Provides a way to concatenate identifiers using metavariable expressions. (unstable, macro_metavar_expr_concat, "1.81.0", Some(124225)), + /// Allows directly represented generic_const_args as the rhs of const items without the + /// `direct_const_arg!` macro. + (incomplete, macroless_const_item_generic_const_args, "CURRENT_RUSTC_VERSION", Some(162540)), /// Allows directly represented generic_const_args without the `direct_const_arg!` macro. (incomplete, macroless_generic_const_args, "1.99.0", Some(159006)), /// Allows `#[marker]` on certain traits allowing overlapping implementations. @@ -856,5 +859,6 @@ pub const INCOMPATIBLE_FEATURES: &[(Symbol, Symbol)] = &[ pub const DEPENDENT_FEATURES: &[(Symbol, &[Symbol])] = &[ (sym::generic_const_args, &[sym::min_generic_const_args]), (sym::macroless_generic_const_args, &[sym::min_generic_const_args]), + (sym::macroless_const_item_generic_const_args, &[sym::min_generic_const_args]), (sym::unsized_const_params, &[sym::adt_const_params]), ]; diff --git a/compiler/rustc_hir_analysis/src/autoderef.rs b/compiler/rustc_hir_analysis/src/autoderef.rs index 01d0c8483ac54..883bfa2b46b9b 100644 --- a/compiler/rustc_hir_analysis/src/autoderef.rs +++ b/compiler/rustc_hir_analysis/src/autoderef.rs @@ -86,7 +86,7 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> { // and Deref, and this has benefits for const and the emitted MIR. let (kind, new_ty) = if let Some(ty) = self.state.cur_ty.builtin_deref(self.include_raw_pointers) { - debug_assert_eq!(ty, self.infcx.resolve_vars_if_possible(ty)); + debug_assert_eq!(ty, self.infcx.deeply_resolve_ignoring_regions(ty)); (AutoderefKind::Builtin, ty) } else if let Some(ty) = self.overloaded_deref_ty(self.state.cur_ty) { // The overloaded deref check already normalizes the pointee type. @@ -123,7 +123,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { param_env, state: AutoderefSnapshot { steps: vec![], - cur_ty: infcx.resolve_vars_if_possible(base_ty), + cur_ty: infcx.deeply_resolve_ignoring_regions(base_ty), obligations: PredicateObligations::new(), at_start: true, reached_recursion_limit: false, @@ -171,7 +171,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { debug!("overloaded_deref_ty({:?}) = ({:?}, {:?})", ty, normalized_ty, obligations); self.state.obligations.extend(obligations); - Some(self.infcx.resolve_vars_if_possible(normalized_ty)) + Some(self.infcx.deeply_resolve_ignoring_regions(normalized_ty)) } #[instrument(level = "debug", skip(self), ret)] diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index d5bc834b831c7..b9f93111e8290 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -427,8 +427,8 @@ fn check_opaque_meets_bounds<'tcx>( } else { // Check that any hidden types found during wf checking match the hidden types that `type_of` sees. for (mut key, mut ty) in infcx.take_opaque_types() { - ty.ty = infcx.resolve_vars_if_possible(ty.ty); - key = infcx.resolve_vars_if_possible(key); + ty.ty = infcx.deeply_resolve_ignoring_regions(ty.ty); + key = infcx.deeply_resolve_ignoring_regions(key); sanity_check_found_hidden_type(tcx, key, ty)?; } Ok(()) @@ -2314,8 +2314,8 @@ pub(super) fn check_coroutine_obligations( // Check that any hidden types found when checking these stalled coroutine obligations // are valid. for (key, ty) in infcx.take_opaque_types() { - let hidden_type = infcx.resolve_vars_if_possible(ty); - let key = infcx.resolve_vars_if_possible(key); + let hidden_type = infcx.deeply_resolve_ignoring_regions(ty); + let key = infcx.deeply_resolve_ignoring_regions(key); sanity_check_found_hidden_type(tcx, key, hidden_type)?; } } else { 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 73013587b27df..280947e655c0b 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -584,9 +584,9 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( .iter() .map(|(_, &(ty, _))| { assert!( - infcx.resolve_vars_if_possible(ty) == ty && ty.is_ty_var(), + infcx.deeply_resolve_ignoring_regions(ty) == ty && ty.is_ty_var(), "{ty:?} should not have been constrained via normalization", - ty = infcx.resolve_vars_if_possible(ty) + ty = infcx.deeply_resolve_ignoring_regions(ty) ); idx += 1; ( @@ -708,7 +708,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( let mut remapped_types = DefIdMap::default(); for (def_id, (ty, args)) in collected_types { - match infcx.fully_resolve(ty) { + match infcx.deeply_resolve_via_region_graph(ty) { Ok(ty) => { // `ty` contains free regions that we created earlier while liberating the // trait fn signature. However, projection normalization expects `ty` to @@ -1296,7 +1296,7 @@ fn check_region_late_boundedness<'tcx>( .inner .borrow_mut() .unwrap_region_constraints() - .opportunistic_resolve_var(tcx, vid) + .shallow_resolve_region_var(tcx, vid) && let ty::ReLateParam(ty::LateParamRegion { kind: ty::LateParamRegionKind::Named(trait_param_def_id), .. @@ -1321,7 +1321,7 @@ fn check_region_late_boundedness<'tcx>( .inner .borrow_mut() .unwrap_region_constraints() - .opportunistic_resolve_var(tcx, vid) + .shallow_resolve_region_var(tcx, vid) && let ty::ReLateParam(ty::LateParamRegion { kind: ty::LateParamRegionKind::Named(impl_param_def_id), .. diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs index 5a6a718b8cc12..471be6043ed65 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs @@ -189,7 +189,9 @@ pub(crate) fn check_refining_return_position_impl_trait_in_trait<'tcx>( return; } // Resolve any lifetime variables that may have been introduced during normalization. - let Ok((trait_bounds, impl_bounds)) = infcx.fully_resolve((trait_bounds, impl_bounds)) else { + let Ok((trait_bounds, impl_bounds)) = + infcx.deeply_resolve_via_region_graph((trait_bounds, impl_bounds)) + else { // If resolution didn't fully complete, we cannot continue checking RPITIT refinement, and // delay a bug as the original code contains load-bearing errors. tcx.dcx().delayed_bug("encountered errors when checking RPITIT refinement (resolution)"); diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index c970799d318fe..f67ed5e44d20e 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -333,7 +333,7 @@ fn orphan_check<'tcx>( let ocx = traits::ObligationCtxt::new(&infcx); let ty = ocx.normalize(&cause, ty::ParamEnv::empty(), Unnormalized::new_wip(user_ty)); - let ty = infcx.resolve_vars_if_possible(ty); + let ty = infcx.deeply_resolve_ignoring_regions(ty); let errors = ocx.try_evaluate_obligations(); if !errors.no_errors() { return Ok(user_ty); @@ -377,7 +377,7 @@ fn orphan_check<'tcx>( id_arg, ); } - infcx.resolve_vars_if_possible(tys) + infcx.deeply_resolve_ignoring_regions(tys) }); OrphanCheckErr::NonLocalInputType(tys) } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 75c0ae86f7592..5c96cf2a13b56 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1539,11 +1539,11 @@ pub fn suggest_impl_trait<'tcx>( ); // FIXME(compiler-errors): We may benefit from resolving regions here. if ocx.try_evaluate_obligations().no_errors() - && let item_ty = infcx.resolve_vars_if_possible(item_ty) + && let item_ty = infcx.deeply_resolve_ignoring_regions(item_ty) && let Some(item_ty) = item_ty.make_suggestable(infcx.tcx, false, None) && let Some(sugg) = formatter( infcx.tcx, - infcx.resolve_vars_if_possible(args), + infcx.deeply_resolve_ignoring_regions(args), trait_def_id, assoc_item_def_id, item_ty, 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 cec65615111a7..d56c094f9f5c3 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 @@ -191,7 +191,7 @@ fn get_impl_args( let assumed_wf_types = ocx.assumed_wf_types_and_report_errors(param_env, impl1_def_id)?; ocx.resolve_regions_and_report_errors(impl1_def_id, param_env, assumed_wf_types)?; - let Ok(impl2_args) = infcx.fully_resolve(impl2_args) else { + let Ok(impl2_args) = infcx.deeply_resolve_via_region_graph(impl2_args) else { let span = tcx.def_span(impl1_def_id); let guar = tcx.dcx().emit_err(GenericArgsOnOverriddenImpl { span }); return Err(guar); diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index e250ec4c7af40..47ba64a591aeb 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -103,7 +103,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => self.check_expr(callee_expr), }; - let expr_ty = self.resolve_vars_with_obligations(original_callee_ty); + let expr_ty = self.deeply_resolve_ignoring_regions_with_obligations(original_callee_ty); let mut autoderef = self.autoderef(callee_expr.span, expr_ty); let mut result = None; @@ -237,7 +237,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { arg_exprs: &'tcx [hir::Expr<'tcx>], autoderef: &Autoderef<'a, 'tcx>, ) -> Option> { - let adjusted_ty = self.resolve_vars_with_obligations(autoderef.final_ty()); + let adjusted_ty = + self.deeply_resolve_ignoring_regions_with_obligations(autoderef.final_ty()); // If the callee is a function pointer or a closure, then we're all set. match *adjusted_ty.kind() { @@ -736,7 +737,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return do_check(); } - resolved_inputs = self.resolve_vars_if_possible(formal_input_tys.to_vec()); + resolved_inputs = self.deeply_resolve_ignoring_regions(formal_input_tys.to_vec()); } // Fool typechecker by placing an adjusted type of the first arg to avoid errors. @@ -873,7 +874,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (rest_span, format!(").{}({rest_snippet}", segment.ident)), ] }; - let self_ty = self.resolve_vars_if_possible(pick.callee.sig.inputs()[0]); + let self_ty = self.deeply_resolve_ignoring_regions(pick.callee.sig.inputs()[0]); diag.multipart_suggestion( format!( "use the `.` operator to call the method `{}{}` on `{self_ty}`", @@ -925,7 +926,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some((removal_span, descr, rustc_hir_pretty::qpath_to_string(self, qpath))); } - let callee_ty = self.resolve_vars_if_possible(callee_ty); + let callee_ty = self.deeply_resolve_ignoring_regions(callee_ty); let mut path = None; let mut err = self.dcx().create_err(diagnostics::InvalidCallee { span: callee_expr.span, diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index a3ed9d0e16e86..d5677ff087ac8 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -96,14 +96,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Result>, ErrorGuaranteed> { debug!("pointer_kind({:?}, {:?})", t, span); - let t = self.resolve_vars_if_possible(t); + let t = self.deeply_resolve_ignoring_regions(t); t.error_reported()?; if self.type_is_sized_modulo_regions(self.param_env, t) { return Ok(Some(PointerKind::Thin)); } - let t = self.resolve_vars_with_obligations(t); + let t = self.deeply_resolve_ignoring_regions_with_obligations(t); Ok(match *t.kind() { ty::Slice(_) | ty::Str => Some(PointerKind::Length), @@ -396,7 +396,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { err.emit(); } CastError::CastToBool => { - let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty); + let expr_ty = fcx.deeply_resolve_ignoring_regions(self.expr_ty); let help = if self.expr_ty.is_numeric() { diagnostics::CannotCastToBoolHelp::Numeric( self.expr_span.shrink_to_hi().with_hi(self.span.hi()), @@ -539,8 +539,8 @@ impl<'a, 'tcx> CastCheck<'tcx> { ) { // Check `impl From for self.cast_ty {}` for accurate suggestion: if let Some(from_trait) = fcx.tcx.get_diagnostic_item(sym::From) { - let ty = fcx.resolve_vars_if_possible(self.cast_ty); - let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty); + let ty = fcx.deeply_resolve_ignoring_regions(self.cast_ty); + let expr_ty = fcx.deeply_resolve_ignoring_regions(self.expr_ty); if fcx .infcx .type_implements_trait(from_trait, [ty, expr_ty], fcx.param_env) @@ -604,8 +604,8 @@ impl<'a, 'tcx> CastCheck<'tcx> { err.emit(); } CastError::SizedUnsizedCast => { - let cast_ty = fcx.resolve_vars_if_possible(self.cast_ty); - let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty); + let cast_ty = fcx.deeply_resolve_ignoring_regions(self.cast_ty); + let expr_ty = fcx.deeply_resolve_ignoring_regions(self.expr_ty); fcx.dcx().emit_err(diagnostics::CastThinPointerToWidePointer { span: self.span, expr_ty, @@ -615,8 +615,8 @@ impl<'a, 'tcx> CastCheck<'tcx> { } CastError::IntToWideCast(known_metadata) => { let expr_if_nightly = fcx.tcx.sess.is_nightly_build().then_some(self.expr_span); - let cast_ty = fcx.resolve_vars_if_possible(self.cast_ty); - let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty); + let cast_ty = fcx.deeply_resolve_ignoring_regions(self.cast_ty); + let expr_ty = fcx.deeply_resolve_ignoring_regions(self.expr_ty); let metadata = known_metadata.unwrap_or("type-specific metadata"); let known_wide = known_metadata.is_some(); let span = self.cast_span; @@ -659,8 +659,8 @@ impl<'a, 'tcx> CastCheck<'tcx> { }); } CastError::CastEnumDrop => { - let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty); - let cast_ty = fcx.resolve_vars_if_possible(self.cast_ty); + let expr_ty = fcx.deeply_resolve_ignoring_regions(self.expr_ty); + let cast_ty = fcx.deeply_resolve_ignoring_regions(self.cast_ty); fcx.dcx().emit_err(diagnostics::CastEnumDrop { span: self.span, expr_ty, cast_ty }); } @@ -707,7 +707,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { self.expr_ty, E0620, "cast to unsized type: `{}` as `{}`", - fcx.resolve_vars_if_possible(self.expr_ty), + fcx.deeply_resolve_ignoring_regions(self.expr_ty), tstr ); match self.expr_ty.kind() { @@ -747,8 +747,8 @@ impl<'a, 'tcx> CastCheck<'tcx> { } else { (false, TRIVIAL_CASTS) }; - let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty); - let cast_ty = fcx.resolve_vars_if_possible(self.cast_ty); + let expr_ty = fcx.deeply_resolve_ignoring_regions(self.expr_ty); + let cast_ty = fcx.deeply_resolve_ignoring_regions(self.cast_ty); fcx.tcx.emit_node_span_lint( lint, self.expr.hir_id, @@ -788,8 +788,8 @@ impl<'a, 'tcx> CastCheck<'tcx> { fn expr_span_for_type_resolution(&self, fcx: &FnCtxt<'a, 'tcx>) -> Span { if let hir::ExprKind::Index(_, idx, _) = self.expr.kind - && fcx.resolve_vars_if_possible(self.expr_ty).is_ty_var() - && fcx.resolve_vars_if_possible(fcx.node_ty(idx.hir_id)).is_ty_var() + && fcx.deeply_resolve_ignoring_regions(self.expr_ty).is_ty_var() + && fcx.deeply_resolve_ignoring_regions(fcx.node_ty(idx.hir_id)).is_ty_var() { index_operand_ambiguity_span(idx) } else { @@ -801,7 +801,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { pub(crate) fn check(mut self, fcx: &FnCtxt<'a, 'tcx>) { let expr_span = self.expr_span_for_type_resolution(fcx); self.expr_ty = fcx.structurally_resolve_type(expr_span, self.expr_ty); - self.cast_ty = fcx.resolve_vars_with_obligations(self.cast_ty); + self.cast_ty = fcx.deeply_resolve_ignoring_regions_with_obligations(self.cast_ty); if self.cast_ty.is_ty_var() { self.cast_ty = if let Some(guar) = self.try_report_ambiguous_binop_for_infer_cast(fcx) { let err = Ty::new_error(fcx.tcx, guar); @@ -863,7 +863,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { .pending_obligations() .into_iter() .filter_map(|mut obligation| { - let predicate = fcx.resolve_vars_if_possible(obligation.predicate); + let predicate = fcx.deeply_resolve_ignoring_regions(obligation.predicate); if !matches!( predicate.kind().skip_binder(), ty::PredicateKind::Clause(ty::ClauseKind::Trait(_)) @@ -877,8 +877,8 @@ impl<'a, 'tcx> CastCheck<'tcx> { else { return None; }; - let lhs_ty = fcx.resolve_vars_if_possible(fcx.node_ty(*lhs_hir_id)); - let rhs_ty = fcx.resolve_vars_if_possible(fcx.node_ty(*rhs_hir_id)); + let lhs_ty = fcx.deeply_resolve_ignoring_regions(fcx.node_ty(*lhs_hir_id)); + let rhs_ty = fcx.deeply_resolve_ignoring_regions(fcx.node_ty(*rhs_hir_id)); if (fcx.tcx.hir_span(*lhs_hir_id).contains(cast_span) && lhs_ty.contains(self.cast_ty)) @@ -1203,8 +1203,8 @@ impl<'a, 'tcx> CastCheck<'tcx> { mut m_cast: ty::TypeAndMut<'tcx>, ) -> Result> { // array-ptr-cast: allow mut-to-mut, mut-to-const, const-to-const - m_expr.ty = fcx.resolve_vars_with_obligations(m_expr.ty); - m_cast.ty = fcx.resolve_vars_with_obligations(m_cast.ty); + m_expr.ty = fcx.deeply_resolve_ignoring_regions_with_obligations(m_expr.ty); + m_cast.ty = fcx.deeply_resolve_ignoring_regions_with_obligations(m_cast.ty); if m_expr.mutbl >= m_cast.mutbl && let ty::Array(ety, _) = m_expr.ty.kind() diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index de2f152011dbe..f6a97f04d99e4 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -60,9 +60,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // closure sooner rather than later, so first examine the expected // type, and see if can glean a closure kind from there. let (expected_sig, expected_kind) = match expected.to_option(self) { - Some(ty) => { - self.deduce_closure_signature(self.resolve_vars_with_obligations(ty), closure.kind) - } + Some(ty) => self.deduce_closure_signature( + self.deeply_resolve_ignoring_regions_with_obligations(ty), + closure.kind, + ), None => (None, None), }; @@ -411,7 +412,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let inferred_fnptr_sig = Ty::new_fn_ptr(self.tcx, inferred_sig.sig); self.demand_eqtype(span, inferred_fnptr_sig, generalized_fnptr_sig); - let resolved_sig = self.resolve_vars_if_possible(generalized_fnptr_sig); + let resolved_sig = self.deeply_resolve_ignoring_regions(generalized_fnptr_sig); if resolved_sig.visit_with(&mut MentionsTy { expected_ty }).is_continue() { expected_sig = Some(ExpectedSig { @@ -517,7 +518,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { cause_span: Option, projection: ty::PolyProjectionClause<'tcx>, ) -> Option> { - let projection = self.resolve_vars_if_possible(projection); + let projection = self.deeply_resolve_ignoring_regions(projection); let arg_param_ty = projection.skip_binder().projection_term.args.type_at(1); debug!(?arg_param_ty); @@ -562,7 +563,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { cause_span: Option, projection: ty::PolyProjectionClause<'tcx>, ) -> Option> { - let projection = self.resolve_vars_if_possible(projection); + let projection = self.deeply_resolve_ignoring_regions(projection); let arg_param_ty = projection.skip_binder().projection_term.args.type_at(1); debug!(?arg_param_ty); @@ -851,8 +852,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { )?; all_obligations.extend(obligations); - let inputs = - supplied_sig.inputs().into_iter().map(|&ty| self.resolve_vars_if_possible(ty)); + let inputs = supplied_sig + .inputs() + .into_iter() + .map(|&ty| self.deeply_resolve_ignoring_regions(ty)); let fn_sig_kind = FnSigKind::default() .set_abi(ExternAbi::RustCall) @@ -959,7 +962,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let closure_span = self.tcx.def_span(body_def_id); let ret_ty = ret_coercion.borrow().expected_ty(); - let ret_ty = self.resolve_vars_with_obligations(ret_ty); + let ret_ty = self.deeply_resolve_ignoring_regions_with_obligations(ret_ty); let get_future_output = |clause: ty::Clause<'tcx>, span| { // Search for a pending obligation like @@ -1064,7 +1067,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Extract the type from the projection. Note that there can // be no bound variables in this type because the "self type" // does not have any regions in it. - let output_ty = self.resolve_vars_if_possible(predicate.term); + let output_ty = self.deeply_resolve_ignoring_regions(predicate.term); debug!("deduce_future_output_from_projection: output_ty={:?}", output_ty); // This is a projection on a Fn trait so will always be a type. Some(output_ty.expect_type()) diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index a54fe8032bc45..b858c6d4a86f3 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -736,7 +736,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { Some(ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred))) if traits.contains(&trait_pred.def_id()) => { - self.resolve_vars_if_possible(trait_pred) + self.deeply_resolve_ignoring_regions(trait_pred) } _ => { coercion.obligations.push(obligation); @@ -1140,7 +1140,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { allow_two_phase: AllowTwoPhase, cause: Option>, ) -> RelateResult<'tcx, Ty<'tcx>> { - let source = self.resolve_vars_with_obligations(expr_ty); + let source = self.deeply_resolve_ignoring_regions_with_obligations(expr_ty); debug!("coercion::try({:?}: {:?} -> {:?})", expr, source, target); let cause = @@ -1335,8 +1335,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { new: &hir::Expr<'_>, new_ty: Ty<'tcx>, ) -> RelateResult<'tcx, Ty<'tcx>> { - let prev_ty = self.resolve_vars_with_obligations(prev_ty); - let new_ty = self.resolve_vars_with_obligations(new_ty); + let prev_ty = self.deeply_resolve_ignoring_regions_with_obligations(prev_ty); + let new_ty = self.deeply_resolve_ignoring_regions_with_obligations(new_ty); debug!( "coercion::try_find_coercion_lub({:?}, {:?}, exprs={:?} exprs)", prev_ty, @@ -1755,7 +1755,7 @@ impl<'tcx> CoerceMany<'tcx> { fcx.set_tainted_by_errors( fcx.dcx().span_delayed_bug(cause.span, "coercion error but no error emitted"), ); - let (expected, found) = fcx.resolve_vars_if_possible((expected, found)); + let (expected, found) = fcx.deeply_resolve_ignoring_regions((expected, found)); let mut err; let mut unsized_return = false; diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 659bb844702aa..830d8905ec8d8 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -261,7 +261,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { mut expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>, allow_two_phase: AllowTwoPhase, ) -> Result, Diag<'a>> { - let expected = self.resolve_vars_with_obligations(expected); + let expected = self.deeply_resolve_ignoring_regions_with_obligations(expected); let e = match self.coerce(expr, checked_ty, expected, allow_two_phase, None) { Ok(ty) => return Ok(ty), @@ -276,7 +276,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { )); let expr = expr.peel_drop_temps(); let cause = self.misc(expr.span); - let expr_ty = self.resolve_vars_if_possible(checked_ty); + let expr_ty = self.deeply_resolve_ignoring_regions(checked_ty); let mut err = self.err_ctxt().report_mismatched_types(&cause, self.param_env, expected, expr_ty, e); @@ -423,7 +423,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Yeet the errors, we're already reporting errors. errs.clear(); }); - Some(self.resolve_vars_if_possible(possible_rcvr_ty)) + Some(self.deeply_resolve_ignoring_regions(possible_rcvr_ty)) }); let Some(rcvr_ty) = possible_rcvr_ty else { return false }; rcvr_ty @@ -546,7 +546,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .borrow() .type_dependent_def_id(parent_expr.hir_id) && let ideal_arg_ty = - self.resolve_vars_if_possible(ideal_method.sig.inputs()[idx + 1]) + self.deeply_resolve_ignoring_regions(ideal_method.sig.inputs()[idx + 1]) && !ideal_arg_ty.has_non_region_infer() { self.emit_type_mismatch_suggestions( diff --git a/compiler/rustc_hir_typeck/src/expectation.rs b/compiler/rustc_hir_typeck/src/expectation.rs index 37c8d7b2ae24e..f3950f2574268 100644 --- a/compiler/rustc_hir_typeck/src/expectation.rs +++ b/compiler/rustc_hir_typeck/src/expectation.rs @@ -46,7 +46,7 @@ impl<'a, 'tcx> Expectation<'tcx> { ) -> Expectation<'tcx> { match *self { ExpectHasType(ety) => { - let ety = fcx.resolve_vars_with_obligations(ety); + let ety = fcx.deeply_resolve_ignoring_regions_with_obligations(ety); if !ety.is_ty_var() { ExpectHasType(ety) } else { NoExpectation } } ExpectRvalueLikeUnsized(ety) => ExpectRvalueLikeUnsized(ety), @@ -93,9 +93,11 @@ impl<'a, 'tcx> Expectation<'tcx> { fn resolve(self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> { match self { NoExpectation => NoExpectation, - ExpectCastableToType(t) => ExpectCastableToType(fcx.resolve_vars_if_possible(t)), - ExpectHasType(t) => ExpectHasType(fcx.resolve_vars_if_possible(t)), - ExpectRvalueLikeUnsized(t) => ExpectRvalueLikeUnsized(fcx.resolve_vars_if_possible(t)), + ExpectCastableToType(t) => ExpectCastableToType(fcx.deeply_resolve_ignoring_regions(t)), + ExpectHasType(t) => ExpectHasType(fcx.deeply_resolve_ignoring_regions(t)), + ExpectRvalueLikeUnsized(t) => { + ExpectRvalueLikeUnsized(fcx.deeply_resolve_ignoring_regions(t)) + } } } @@ -112,7 +114,7 @@ impl<'a, 'tcx> Expectation<'tcx> { /// such a constraint, if it exists. pub(super) fn only_has_type(self, fcx: &FnCtxt<'a, 'tcx>) -> Option> { match self { - ExpectHasType(ty) => Some(fcx.resolve_vars_if_possible(ty)), + ExpectHasType(ty) => Some(fcx.deeply_resolve_ignoring_regions(ty)), NoExpectation | ExpectCastableToType(_) | ExpectRvalueLikeUnsized(_) => None, } } diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index cc2be9d392b36..06dbd06eb191b 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -82,7 +82,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // While we don't allow *arbitrary* coercions here, we *do* allow // coercions from ! to `expected`. - if self.resolve_vars_with_obligations(ty).is_never() + if self.deeply_resolve_ignoring_regions_with_obligations(ty).is_never() && self.tcx.expr_guaranteed_to_constitute_read_for_never(expr) { if let Some(adjustments) = self.typeck_results.borrow().adjustments().get(expr.hir_id) { @@ -271,7 +271,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) => self.check_expr_path(qpath, expr, call_expr_and_args), _ => self.check_expr_kind(expr, expected), }; - let ty = self.resolve_vars_if_possible(ty); + let ty = self.deeply_resolve_ignoring_regions(ty); // Warn for non-block expressions with diverging children. match expr.kind { @@ -300,7 +300,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // unless it's a place expression that isn't being read from, in which case // diverging would be unsound since we may never actually read the `!`. // e.g. `let _ = *never_ptr;` with `never_ptr: *const !`. - if self.resolve_vars_with_obligations(ty).is_never() + if self.deeply_resolve_ignoring_regions_with_obligations(ty).is_never() && self.tcx.expr_guaranteed_to_constitute_read_for_never(expr) { self.diverges.set(self.diverges.get() | Diverges::always(expr.span)); @@ -464,7 +464,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx> { let hint = expected.only_has_type(self).map_or(NoExpectation, |ty| { - match self.resolve_vars_with_obligations(ty).kind() { + match self.deeply_resolve_ignoring_regions_with_obligations(ty).kind() { ty::Ref(_, ty, _) | ty::RawPtr(ty, _) => { if oprnd.is_syntactic_place_expr() { // Places may legitimately have unsized types. @@ -1480,7 +1480,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Expectation<'tcx>, ) -> Ty<'tcx> { let rcvr_t = self.check_expr(rcvr); - let rcvr_t = self.resolve_vars_with_obligations(rcvr_t); + let rcvr_t = self.deeply_resolve_ignoring_regions_with_obligations(rcvr_t); match self.lookup_method(rcvr_t, segment, segment.ident.span, expr, rcvr, args) { Ok(method) => { @@ -1551,9 +1551,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Find the type of `e`. Supply hints based on the type we are casting to, // if appropriate. let t_cast = self.lower_ty_saving_user_provided_ty(t); - let t_cast = self.resolve_vars_if_possible(t_cast); + let t_cast = self.deeply_resolve_ignoring_regions(t_cast); let t_expr = self.check_expr_with_expectation(e, ExpectCastableToType(t_cast)); - let t_expr = self.resolve_vars_if_possible(t_expr); + let t_expr = self.deeply_resolve_ignoring_regions(t_expr); // Eagerly check for some obvious errors. if let Err(guar) = (t_expr, t_cast).error_reported() { @@ -1675,11 +1675,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let coerce_to = expected .to_option(self) .and_then(|uty| { - self.resolve_vars_with_obligations(uty) + self.deeply_resolve_ignoring_regions_with_obligations(uty) .builtin_index() // Avoid using the original type variable as the coerce_to type, as it may resolve // during the first coercion instead of being the LUB type. - .filter(|t| !self.resolve_vars_with_obligations(*t).is_ty_var()) + .filter(|t| { + !self.deeply_resolve_ignoring_regions_with_obligations(*t).is_ty_var() + }) }) .unwrap_or_else(|| self.next_ty_var(expr.span)); let mut coerce = CoerceMany::with_capacity(coerce_to, args.len()); @@ -1804,7 +1806,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Ty<'tcx> { let mut expectations = expected .only_has_type(self) - .and_then(|ty| self.resolve_vars_with_obligations(ty).opt_tuple_fields()) + .and_then(|ty| { + self.deeply_resolve_ignoring_regions_with_obligations(ty).opt_tuple_fields() + }) .unwrap_or_default() .iter(); @@ -1878,7 +1882,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) { let tcx = self.tcx; - let adt_ty = self.resolve_vars_with_obligations(adt_ty); + let adt_ty = self.deeply_resolve_ignoring_regions_with_obligations(adt_ty); let adt_ty_hint = expected.only_has_type(self).and_then(|expected| { self.fudge_inference_if_ok(|| { let ocx = ObligationCtxt::new(self); @@ -1886,7 +1890,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if !ocx.try_evaluate_obligations().no_errors() { return Err(TypeError::Mismatch); } - Ok(self.resolve_vars_if_possible(adt_ty)) + Ok(self.deeply_resolve_ignoring_regions(adt_ty)) }) .ok() }); @@ -2144,7 +2148,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - self.resolve_vars_if_possible(fru_ty) + self.deeply_resolve_ignoring_regions(fru_ty) }) .collect(); // The use of fresh args that we have subtyped against @@ -2168,7 +2172,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let fresh_base_ty = Ty::new_adt(self.tcx, *adt, fresh_args); self.check_expr_has_type_or_error( base_expr, - self.resolve_vars_if_possible(fresh_base_ty), + self.deeply_resolve_ignoring_regions(fresh_base_ty), |_| {}, ); fru_tys diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index e8f912165a4c5..47079ccbb1804 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -157,7 +157,7 @@ pub trait TypeInformationCtxt<'tcx> { fn typeck_results(&self) -> Self::TypeckResults<'_>; - fn resolve_vars_if_possible>>(&self, t: T) -> T; + fn deeply_resolve_ignoring_regions>>(&self, t: T) -> T; fn structurally_resolve_type(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx>; @@ -188,8 +188,8 @@ impl<'tcx> TypeInformationCtxt<'tcx> for &FnCtxt<'_, 'tcx> { self.typeck_results.borrow() } - fn resolve_vars_if_possible>>(&self, t: T) -> T { - self.infcx.resolve_vars_if_possible(t) + fn deeply_resolve_ignoring_regions>>(&self, t: T) -> T { + self.infcx.deeply_resolve_ignoring_regions(t) } fn structurally_resolve_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> { @@ -242,7 +242,7 @@ impl<'tcx> TypeInformationCtxt<'tcx> for (&LateContext<'tcx>, LocalDefId) { ty } - fn resolve_vars_if_possible>>(&self, t: T) -> T { + fn deeply_resolve_ignoring_regions>>(&self, t: T) -> T { t } @@ -1127,7 +1127,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx ) -> Result, Cx::Error> { match ty { Some(ty) => { - let ty = self.cx.resolve_vars_if_possible(ty); + let ty = self.cx.deeply_resolve_ignoring_regions(ty); self.cx.error_reported_in_ty(ty)?; Ok(ty) } @@ -1266,7 +1266,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx where F: FnOnce() -> Result, Cx::Error>, { - let target = self.cx.resolve_vars_if_possible(adjustment.target); + let target = self.cx.deeply_resolve_ignoring_regions(adjustment.target); match adjustment.kind { adjustment::Adjust::Deref(deref_kind) => { // Equivalent to *expr or something similar. diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index b7906de6dac0c..9a7c381a2dc39 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -108,11 +108,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } /// Resolves type and const variables in `t` if possible. Unlike the infcx - /// version (resolve_vars_if_possible), this version will + /// version (deeply_resolve_ignoring_regions), this version will /// also select obligations if it seems useful, in an effort /// to get more type information. #[instrument(skip(self), level = "debug", ret)] - pub(crate) fn resolve_vars_with_obligations>>( + pub(crate) fn deeply_resolve_ignoring_regions_with_obligations< + T: TypeFoldable>, + >( &self, mut t: T, ) -> T { @@ -123,7 +125,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } // If `t` is a type variable, see whether we already know what it is. - t = self.resolve_vars_if_possible(t); + t = self.deeply_resolve_ignoring_regions(t); if !t.has_non_region_infer() { debug!(?t); return t; @@ -134,7 +136,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // indirect dependencies that don't seem worth tracking // precisely. self.select_obligations_where_possible(|_| {}); - self.resolve_vars_if_possible(t) + self.deeply_resolve_ignoring_regions(t) } pub(crate) fn record_deferred_call_resolution( @@ -166,7 +168,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { #[inline] pub(crate) fn write_ty(&self, id: HirId, ty: Ty<'tcx>) { - debug!("write_ty({:?}, {:?}) in fcx {}", id, self.resolve_vars_if_possible(ty), self.tag()); + debug!( + "write_ty({:?}, {:?}) in fcx {}", + id, + self.deeply_resolve_ignoring_regions(ty), + self.tag() + ); let mut typeck = self.typeck_results.borrow_mut(); let mut node_ty = typeck.node_types_mut(); @@ -1473,7 +1480,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { sp: Span, ct: ty::Const<'tcx>, ) -> ty::Const<'tcx> { - let ct = self.resolve_vars_with_obligations(ct); + let ct = self.deeply_resolve_ignoring_regions_with_obligations(ct); if self.next_trait_solver() && let ty::ConstKind::Alias(..) = ct.kind() @@ -1508,7 +1515,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// If no resolution is possible, then an error is reported. /// Numeric inference variables may be left unresolved. pub(crate) fn structurally_resolve_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> { - let ty = self.resolve_vars_with_obligations(ty); + let ty = self.deeply_resolve_ignoring_regions_with_obligations(ty); if !ty.is_ty_var() { ty } else { self.type_must_be_known_at_this_point(sp, ty) } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs index be24a5e7d0b8c..ea0aa9db46a9c 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs @@ -196,18 +196,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let hir::ExprKind::Index(indexed_expr, idx, _) = rhs_expr.kind else { return false; }; - if !self.resolve_vars_if_possible(self.node_ty(idx.hir_id)).is_ty_var() { + if !self.deeply_resolve_ignoring_regions(self.node_ty(idx.hir_id)).is_ty_var() { return false; } - let lhs_ty = self.resolve_vars_if_possible(self.node_ty(lhs_expr.hir_id)); - let indexed_ty = self.resolve_vars_if_possible(self.node_ty(indexed_expr.hir_id)); + let lhs_ty = self.deeply_resolve_ignoring_regions(self.node_ty(lhs_expr.hir_id)); + let indexed_ty = self.deeply_resolve_ignoring_regions(self.node_ty(indexed_expr.hir_id)); let rhs_ty = match *indexed_ty.kind() { ty::Array(element_ty, _) | ty::Slice(element_ty) => element_ty, ty::Ref(_, pointee_ty, _) => match *pointee_ty.kind() { ty::Array(element_ty, _) | ty::Slice(element_ty) => element_ty, - _ => self.resolve_vars_if_possible(self.node_ty(rhs_expr.hir_id)), + _ => self.deeply_resolve_ignoring_regions(self.node_ty(rhs_expr.hir_id)), }, - _ => self.resolve_vars_if_possible(self.node_ty(rhs_expr.hir_id)), + _ => self.deeply_resolve_ignoring_regions(self.node_ty(rhs_expr.hir_id)), }; if !self.binop_accepts_types(binop.node, lhs_ty, rhs_ty) { return false; diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index ba44d1966d971..9859a1ad27444 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -246,7 +246,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut expected_input_tys: Option> = expectation .only_has_type(self) .and_then(|expected_output| { - let formal_output = self.resolve_vars_with_obligations(formal_output); + let formal_output = + self.deeply_resolve_ignoring_regions_with_obligations(formal_output); // FIXME(#149379): This operation results in expected input // types which are potentially not well-formed or for whom the // function where-bounds don't actually hold. This results @@ -283,7 +284,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Ok(Some( formal_input_tys .iter() - .map(|&ty| self.resolve_vars_if_possible(ty)) + .map(|&ty| self.deeply_resolve_ignoring_regions(ty)) .collect::>(), )) }) @@ -387,7 +388,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Cause selection errors caused by resolving a single argument to point at the // argument and not the call. This lets us customize the span pointed to in the // fulfillment error to be more accurate. - let coerced_ty = self.resolve_vars_with_obligations(coerced_ty); + let coerced_ty = self.deeply_resolve_ignoring_regions_with_obligations(coerced_ty); let coerce_error = self.coerce(provided_arg, checked_ty, coerced_ty, AllowTwoPhase::Yes, None).err(); @@ -541,7 +542,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } ty::FnDef(..) => { let fn_ptr = Ty::new_fn_ptr(self.tcx, arg_ty.fn_sig(self.tcx)); - let fn_ptr = self.resolve_vars_if_possible(fn_ptr).to_string(); + let fn_ptr = self.deeply_resolve_ignoring_regions(fn_ptr).to_string(); let fn_item_spa = arg.span; tcx.sess.dcx().emit_err(diagnostics::PassFnItemToVariadicFunction { @@ -572,7 +573,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .iter() .copied() .zip_eq(expected_input_tys.iter().copied()) - .map(|vars| self.resolve_vars_if_possible(vars)), + .map(|vars| self.deeply_resolve_ignoring_regions(vars)), ); self.report_arg_errors( @@ -652,7 +653,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let formal_input_tupled_ty = formal_input_tys[first_tupled_arg_index_usz]; // Keep the type variable if the argument is splatted, so we can force it to be a tuple later. let tuple_type = if tuple_arguments.is_splatted() { - let callee_tuple_type = self.resolve_vars_with_obligations(formal_input_tupled_ty); + let callee_tuple_type = + self.deeply_resolve_ignoring_regions_with_obligations(formal_input_tupled_ty); if callee_tuple_type.is_ty_var() && let Some(tupled_args_count) = tupled_args_count { @@ -1833,7 +1835,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { param.param.span(), format!( "this parameter needs to match the {} type of {deps_list}", - self.resolve_vars_if_possible( + self.deeply_resolve_ignoring_regions( formal_and_expected_inputs[param.deps[0]].1 ) .sort_string(self.tcx), @@ -1857,7 +1859,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { format!( "{deps_list} need{} to match the {} type of this parameter", pluralize!((deps.len() != 1) as u32), - self.resolve_vars_if_possible(expected_ty) + self.deeply_resolve_ignoring_regions(expected_ty) .sort_string(self.tcx), ), ); @@ -2036,7 +2038,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let expected_display_type = self - .resolve_vars_if_possible(formal_and_expected_inputs[idx].1) + .deeply_resolve_ignoring_regions(formal_and_expected_inputs[idx].1) .sort_string(self.tcx); let label = if idxs_matched == params_with_generics.len() - 1 { format!( @@ -3331,7 +3333,7 @@ impl<'a, 'tcx> ArgsCtxt<'a, 'tcx> { .expr_ty_adjusted_opt(expr) .unwrap_or_else(|| Ty::new_misc_error(self.call_ctxt.fn_ctxt.tcx)); ( - self.call_ctxt.fn_ctxt.resolve_vars_if_possible(ty), + self.call_ctxt.fn_ctxt.deeply_resolve_ignoring_regions(ty), self.normalize_span(expr.span), ) }) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs index 8b76a5eb44db7..ee9ebfea1fb38 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs @@ -139,7 +139,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } obligations_for_self_ty.retain_mut(|obligation| { - obligation.predicate = self.resolve_vars_if_possible(obligation.predicate); + obligation.predicate = self.deeply_resolve_ignoring_regions(obligation.predicate); !obligation.predicate.has_placeholders() }); obligations_for_self_ty diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 3e2c2e8cc3944..d565bc63e0e47 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -262,8 +262,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { found_type: Ty<'tcx>, ) -> bool { let tcx = self.tcx; - let expected = self.resolve_vars_if_possible(expected_type); - let found = self.resolve_vars_if_possible(found_type); + let expected = self.deeply_resolve_ignoring_regions(expected_type); + let found = self.deeply_resolve_ignoring_regions(found_type); if expected.references_error() || found.references_error() || expected.is_unit() { return false; @@ -992,7 +992,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let found = - self.resolve_numeric_literals_with_default(self.resolve_vars_if_possible(found)); + self.resolve_numeric_literals_with_default(self.deeply_resolve_ignoring_regions(found)); // Only suggest changing the return type for methods that // haven't set a return type at all (and aren't `fn main()`, impl or closure). match &fn_decl.output { @@ -1322,7 +1322,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if !expected.is_unit() { return; } - let found = self.resolve_vars_if_possible(found); + let found = self.deeply_resolve_ignoring_regions(found); let innermost_loop = if self.is_loop(id) { Some(self.tcx.hir_node(id)) diff --git a/compiler/rustc_hir_typeck/src/inline_asm.rs b/compiler/rustc_hir_typeck/src/inline_asm.rs index e0fccce9577eb..1303c2c2e9e0f 100644 --- a/compiler/rustc_hir_typeck/src/inline_asm.rs +++ b/compiler/rustc_hir_typeck/src/inline_asm.rs @@ -46,7 +46,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { fn expr_ty(&self, expr: &hir::Expr<'tcx>) -> Ty<'tcx> { let ty = self.fcx.typeck_results.borrow().expr_ty_adjusted(expr); - let ty = self.fcx.resolve_vars_with_obligations(ty); + let ty = self.fcx.deeply_resolve_ignoring_regions_with_obligations(ty); if ty.has_non_region_infer() { Ty::new_misc_error(self.tcx()) } else { @@ -61,7 +61,9 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { if self.fcx.type_is_sized_modulo_regions(self.fcx.param_env, ty) { return true; } - if let ty::Foreign(..) = self.fcx.resolve_vars_with_obligations(ty).kind() { + if let ty::Foreign(..) = + self.fcx.deeply_resolve_ignoring_regions_with_obligations(ty).kind() + { return true; } false diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 6e6ded6c59ea1..c0aa8b8f55c65 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -2147,8 +2147,14 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { for nested_obligation in candidate.nested_obligations() { if !self.infcx.predicate_may_hold(&nested_obligation) { possibly_unsatisfied_predicates.push(( - self.resolve_vars_if_possible(nested_obligation.predicate), - Some(self.resolve_vars_if_possible(obligation.predicate)), + self.deeply_resolve_ignoring_regions( + nested_obligation.predicate, + ), + Some( + self.deeply_resolve_ignoring_regions( + obligation.predicate, + ), + ), Some(nested_obligation.cause), )); } @@ -2198,9 +2204,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // Evaluate those obligations to see if they might possibly hold. for error in ocx.try_evaluate_obligations() { result = ProbeResult::NoMatch; - let nested_predicate = self.resolve_vars_if_possible(error.obligation.predicate); + let nested_predicate = + self.deeply_resolve_ignoring_regions(error.obligation.predicate); if let Some(trait_predicate) = trait_predicate - && nested_predicate == self.resolve_vars_if_possible(trait_predicate) + && nested_predicate == self.deeply_resolve_ignoring_regions(trait_predicate) { // Don't report possibly unsatisfied predicates if the root // trait obligation from a `TraitCandidate` is unsatisfied. @@ -2208,7 +2215,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } else { possibly_unsatisfied_predicates.push(( nested_predicate, - Some(self.resolve_vars_if_possible(error.root_obligation.predicate)) + Some(self.deeply_resolve_ignoring_regions(error.root_obligation.predicate)) .filter(|root_predicate| *root_predicate != nested_predicate), Some(error.obligation.cause), )); @@ -2329,7 +2336,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { return false; } - !self.resolve_vars_if_possible(self_ty).is_ty_var() + !self.deeply_resolve_ignoring_regions(self_ty).is_ty_var() }); if constrained_opaque { debug!("opaque type has been constrained"); diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index e59ca32aba116..f5158dcdfb998 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1252,7 +1252,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { within_macro_span: Option, ) -> ErrorGuaranteed { let tcx = self.tcx; - let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty); + let rcvr_ty = self.deeply_resolve_ignoring_regions(rcvr_ty); if let Err(guar) = rcvr_ty.error_reported() { return guar; @@ -2254,7 +2254,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { format!("{item_kind} `{item_name}` is available on `{prev_match}`"), ); } - let rcvr_ty = self.resolve_vars_if_possible( + let rcvr_ty = self.deeply_resolve_ignoring_regions( self.typeck_results .borrow() .expr_ty_adjusted_opt(rcvr_expr) @@ -3305,7 +3305,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let field_ty = field.ty(tcx, args).skip_norm_wip(); // Skip `_`, since that'll just lead to ambiguity. - if self.resolve_vars_if_possible(field_ty).is_ty_var() { + if self.deeply_resolve_ignoring_regions(field_ty).is_ty_var() { return None; } @@ -3325,7 +3325,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(ret_ty) = self .ret_coercion .as_ref() - .map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty())) + .map(|c| self.deeply_resolve_ignoring_regions(c.borrow().expected_ty())) && let ty::Adt(kind, _) = ret_ty.kind() && tcx.get_diagnostic_item(diagnostic_item) == Some(kind.did()) { @@ -3881,7 +3881,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return_type: Option>, ) { let Some(output_ty) = self.tcx.get_impl_future_output_ty(ty) else { return }; - let output_ty = self.resolve_vars_if_possible(output_ty); + let output_ty = self.deeply_resolve_ignoring_regions(output_ty); let method_exists = self.method_exists_for_diagnostic(item_name, output_ty, call.hir_id, return_type); debug!("suggest_await_before_method: is_method_exist={}", method_exists); diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index c28976555432b..d5e4da7e4250e 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -221,7 +221,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.check_expr(lhs_expr) } }; - let lhs_ty = self.resolve_vars_with_obligations(lhs_ty); + let lhs_ty = self.deeply_resolve_ignoring_regions_with_obligations(lhs_ty); // N.B., as we have not yet type-checked the RHS, we don't have the // type at hand. Make a variable to represent it. The whole reason @@ -256,7 +256,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } }, ); - let rhs_ty = self.resolve_vars_with_obligations(rhs_ty); + let rhs_ty = self.deeply_resolve_ignoring_regions_with_obligations(rhs_ty); let return_ty = self.overloaded_binop_ret_ty( expr, lhs_expr, rhs_expr, op, expected, lhs_ty, result, rhs_ty, @@ -979,7 +979,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { method.sig.output() } Err(errors) => { - let actual = self.resolve_vars_if_possible(operand_ty); + let actual = self.deeply_resolve_ignoring_regions(operand_ty); let guar = actual.error_reported().err().unwrap_or_else(|| { let mut file = None; let ty_str = self.tcx.short_string(actual, &mut file); diff --git a/compiler/rustc_hir_typeck/src/opaque_types.rs b/compiler/rustc_hir_typeck/src/opaque_types.rs index ae46378cd8241..f2d63151f89f2 100644 --- a/compiler/rustc_hir_typeck/src/opaque_types.rs +++ b/compiler/rustc_hir_typeck/src/opaque_types.rs @@ -93,7 +93,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> { error_on_missing_defining_use: bool, ) { for entry in opaque_types.iter_mut() { - *entry = self.resolve_vars_if_possible(*entry); + *entry = self.deeply_resolve_ignoring_regions(*entry); } debug!(?opaque_types); diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 7413215b15ba1..432ade94f49d8 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -497,7 +497,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let expected = if let AdjustMode::Peel { .. } = adjust_mode && pat.default_binding_modes { - self.resolve_vars_with_obligations(expected) + self.deeply_resolve_ignoring_regions_with_obligations(expected) } else { expected }; @@ -791,14 +791,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { lt.kind ); } - // Call `resolve_vars_if_possible` here for inline const blocks. - let lit_ty = self.resolve_vars_if_possible(self.check_pat_expr_unadjusted(lt)); + // Call `deeply_resolve_ignoring_regions` here for inline const blocks. + let lit_ty = self.deeply_resolve_ignoring_regions(self.check_pat_expr_unadjusted(lt)); // If `deref_patterns` is enabled, allow `if let "foo" = &&"foo" {}`. if self.tcx.features().deref_patterns() { let mut peeled_ty = lit_ty; let mut pat_ref_layers = 0; while let ty::Ref(_, inner_ty, mutbl) = - *self.resolve_vars_with_obligations(peeled_ty).kind() + *self.deeply_resolve_ignoring_regions_with_obligations(peeled_ty).kind() { // We rely on references at the head of constants being immutable. debug_assert!(mutbl.is_not()); @@ -944,7 +944,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match *expected.kind() { // Allow `b"...": &[u8]` ty::Ref(_, inner_ty, _) - if self.resolve_vars_with_obligations(inner_ty).is_slice() => + if self + .deeply_resolve_ignoring_regions_with_obligations(inner_ty) + .is_slice() => { trace!(?expr.hir_id.local_id, "polymorphic byte string lit"); pat_ty = Ty::new_imm_ref( @@ -973,7 +975,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // string literal patterns to have type `str`. This is accounted for when lowering to MIR. if self.tcx.features().deref_patterns() && matches!(lit_kind, ast::LitKind::Str(..)) - && self.resolve_vars_with_obligations(expected).is_str() + && self.deeply_resolve_ignoring_regions_with_obligations(expected).is_str() { pat_ty = self.tcx.types.str_; } @@ -991,7 +993,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let cause = self.pattern_cause(ti, span); if let Err(mut err) = self.demand_suptype_with_origin(&cause, expected, pat_ty) { // If scrutinee is String and pattern is &str, suggest .as_str() - let expected = self.resolve_vars_with_obligations(expected); + let expected = self.deeply_resolve_ignoring_regions_with_obligations(expected); if let ty::Adt(adt, _) = expected.kind() && self.tcx.is_lang_item(adt.did(), LangItem::String) && pat_ty.is_ref() @@ -1029,7 +1031,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // be peeled to `str` while ty here is still `&str`, if we don't // err early here, a rather confusing unification error will be // emitted instead). - let ty = self.resolve_vars_with_obligations(ty); + let ty = self.deeply_resolve_ignoring_regions_with_obligations(ty); let fail = !(ty.is_numeric() || ty.is_char() || ty.is_ty_var() || ty.references_error()); Some((fail, ty, expr.span)) @@ -1108,13 +1110,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "only `char` and numeric types are allowed in range patterns" ); let msg = |ty| { - let ty = self.resolve_vars_if_possible(ty); + let ty = self.deeply_resolve_ignoring_regions(ty); format!("this is of type `{ty}` but it should be `char` or numeric") }; let mut one_side_err = |first_span, first_ty, second: Option<(bool, Ty<'tcx>, Span)>| { err.span_label(first_span, msg(first_ty)); if let Some((_, ty, sp)) = second { - let ty = self.resolve_vars_if_possible(ty); + let ty = self.deeply_resolve_ignoring_regions(ty); self.endpoint_has_type(&mut err, sp, ty); } }; @@ -1290,7 +1292,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) { let var_ty = self.local_ty(span, var_id); if let Err(mut err) = self.demand_eqtype_pat_diag(span, var_ty, ty, ti) { - let var_ty = self.resolve_vars_if_possible(var_ty); + let var_ty = self.deeply_resolve_ignoring_regions(var_ty); let msg = format!("first introduced with type `{var_ty}` here"); err.span_label(self.tcx.hir_span(var_id), msg); let in_match = self.tcx.hir_parent_iter(var_id).any(|(_, n)| { @@ -1308,7 +1310,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &mut err, span, var_ty, - self.resolve_vars_if_possible(ty), + self.deeply_resolve_ignoring_regions(ty), ba, ); err.emit(); @@ -2734,7 +2736,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { [source_ty], ); let target_ty = self.normalize(span, Unnormalized::new_wip(target_ty)); - self.resolve_vars_with_obligations(target_ty) + self.deeply_resolve_ignoring_regions_with_obligations(target_ty) } /// Check if the interior of a deref pattern (either explicit or implicit) has any `ref mut` @@ -2782,7 +2784,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pat_info.max_ref_mutbl = pat_info.max_ref_mutbl.cap_to_weakly_not(pat_prefix_span); } - expected = self.resolve_vars_with_obligations(expected); + expected = self.deeply_resolve_ignoring_regions_with_obligations(expected); // Determine whether we're consuming an inherited reference and resetting the default // binding mode, based on edition and enabled experimental features. if let ByRef::Yes(inh_pin, inh_mut) = pat_info.binding_mode @@ -3073,7 +3075,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Ty<'tcx>, pat_info: PatInfo<'tcx>, ) -> Ty<'tcx> { - let expected = self.resolve_vars_with_obligations(expected); + let expected = self.deeply_resolve_ignoring_regions_with_obligations(expected); // If the pattern is irrefutable and `expected` is an infer ty, we try to equate it // to an array if the given pattern allows it. See issue #76342 @@ -3251,7 +3253,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && let Some(span) = ti.span && let Some(_) = ti.origin_expr { - let resolved_ty = self.resolve_vars_if_possible(ti.expected); + let resolved_ty = self.deeply_resolve_ignoring_regions(ti.expected); let (is_slice_or_array_or_vector, resolved_ty) = self.is_slice_or_array_or_vector(resolved_ty); match resolved_ty.kind() { diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs index b3ac237adf956..56112235d3d24 100644 --- a/compiler/rustc_hir_typeck/src/place_op.rs +++ b/compiler/rustc_hir_typeck/src/place_op.rs @@ -74,7 +74,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Span, base_expr: &hir::Expr<'_>, ) -> Option<(Ty<'tcx>, Ty<'tcx>)> { - let ty = self.resolve_vars_if_possible(ty); + let ty = self.deeply_resolve_ignoring_regions(ty); let mut err = self.dcx().struct_span_err( span, format!("negative integers cannot be used to index on a `{ty}`"), diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 167cb1f272533..e9f7cf1e7783e 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -271,7 +271,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } }; - let args = self.resolve_vars_if_possible(args); + let args = self.deeply_resolve_ignoring_regions(args); let closure_def_id = closure_def_id.expect_local(); assert_eq!(self.tcx.hir_body_owner_def_id(body.id()), closure_def_id); @@ -1329,7 +1329,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let root_var_min_capture_list = min_captures.and_then(|m| m.get(&var_hir_id))?; - let ty = self.resolve_vars_if_possible(self.node_ty(var_hir_id)); + let ty = self.deeply_resolve_ignoring_regions(self.node_ty(var_hir_id)); let ty = match closure_clause { hir::CaptureBy::Value { .. } => ty, // For move closure the capture kind should be by value @@ -1427,7 +1427,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { closure_clause: hir::CaptureBy, var_hir_id: HirId, ) -> Option> { - let ty = self.resolve_vars_if_possible(self.node_ty(var_hir_id)); + let ty = self.deeply_resolve_ignoring_regions(self.node_ty(var_hir_id)); // FIXME(#132279): Using `non_body_analysis` here feels wrong. if !ty.has_significant_drop( diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index b71290b658744..f4fe38924351a 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -807,8 +807,9 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { let obligations = self.fcx.take_hir_typeck_potentially_region_dependent_goals(); if self.fcx.tainted_by_errors().is_none() { for obligation in obligations { - let (predicate, mut cause) = - self.fcx.resolve_vars_if_possible((obligation.predicate, obligation.cause)); + let (predicate, mut cause) = self + .fcx + .deeply_resolve_ignoring_regions((obligation.predicate, obligation.cause)); if predicate.has_non_region_infer() { self.fcx.dcx().span_delayed_bug( cause.span, @@ -833,7 +834,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { where T: TypeFoldable>, { - let value = self.fcx.resolve_vars_if_possible(value); + let value = self.fcx.deeply_resolve_ignoring_regions(value); let mut goals = vec![]; let value = @@ -847,7 +848,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { goals .into_iter() .map(|pred| { - self.fcx.resolve_vars_if_possible(pred).fold_with(&mut Resolver::new( + self.fcx.deeply_resolve_ignoring_regions(pred).fold_with(&mut Resolver::new( self.fcx, span, self.body, @@ -876,7 +877,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { where T: TypeFoldable>, { - let value = self.fcx.resolve_vars_if_possible(value); + let value = self.fcx.deeply_resolve_ignoring_regions(value); let mut goals = vec![]; let value = diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 9b3deac32222b..4fe57994057cc 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -165,7 +165,7 @@ impl CanonicalizeMode for CanonicalizeQueryResponse { .inner .borrow_mut() .unwrap_region_constraints() - .opportunistic_resolve_var(canonicalizer.tcx, vid); + .shallow_resolve_region_var(canonicalizer.tcx, vid); debug!( "canonical: region var found with vid {vid:?}, \ opportunistically resolved to {r:?}", @@ -183,7 +183,7 @@ impl CanonicalizeMode for CanonicalizeQueryResponse { .inner .borrow_mut() .unwrap_region_constraints() - .probe_value(vid) + .try_resolve_region_var(vid) .unwrap_err(); canonicalizer.canonical_var_for_region(CanonicalVarKind::Region(universe), r) } @@ -363,7 +363,7 @@ impl<'cx, 'tcx> TypeFolder> for Canonicalizer<'cx, 'tcx> { } ty::Infer(ty::IntVar(vid)) => { - let nt = self.infcx.unwrap().opportunistic_resolve_int_var(vid); + let nt = self.infcx.unwrap().shallow_resolve_int_var(vid); if nt != t { return self.fold_ty(nt); } else { @@ -371,7 +371,7 @@ impl<'cx, 'tcx> TypeFolder> for Canonicalizer<'cx, 'tcx> { } } ty::Infer(ty::FloatVar(vid)) => { - let nt = self.infcx.unwrap().opportunistic_resolve_float_var(vid); + let nt = self.infcx.unwrap().shallow_resolve_float_var(vid); if nt != t { return self.fold_ty(nt); } else { diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs index f9b08efad88cf..4d90e60736995 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -82,14 +82,14 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { } } - fn universe_of_lt(&self, lt: ty::RegionVid) -> Option { - match self.inner.borrow_mut().unwrap_region_constraints().probe_value(lt) { + fn universe_of_region(&self, lt: ty::RegionVid) -> Option { + match self.inner.borrow_mut().unwrap_region_constraints().try_resolve_region_var(lt) { Err(universe) => Some(universe), Ok(_) => None, } } - fn universe_of_ct(&self, ct: ty::ConstVid) -> Option { + fn universe_of_const(&self, ct: ty::ConstVid) -> Option { match self.try_resolve_const_var(ct) { Err(universe) => Some(universe), Ok(_) => None, @@ -118,30 +118,27 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { self.root_const_var(var) } - fn opportunistic_resolve_ty_var(&self, vid: ty::TyVid) -> Ty<'tcx> { - match self.try_resolve_ty_var(vid) { - Ok(ty) => ty, - Err(_) => Ty::new_var(self.tcx, self.root_var(vid)), - } + fn shallow_resolve_ty_var(&self, vid: ty::TyVid) -> Ty<'tcx> { + self.shallow_resolve_ty_var(vid) } - fn opportunistic_resolve_int_var(&self, vid: ty::IntVid) -> Ty<'tcx> { - self.opportunistic_resolve_int_var(vid) + fn shallow_resolve_int_var(&self, vid: ty::IntVid) -> Ty<'tcx> { + self.shallow_resolve_int_var(vid) } - fn opportunistic_resolve_float_var(&self, vid: ty::FloatVid) -> Ty<'tcx> { - self.opportunistic_resolve_float_var(vid) + fn shallow_resolve_float_var(&self, vid: ty::FloatVid) -> Ty<'tcx> { + self.shallow_resolve_float_var(vid) } - fn opportunistic_resolve_ct_var(&self, vid: ty::ConstVid) -> ty::Const<'tcx> { - match self.try_resolve_const_var(vid) { - Ok(ct) => ct, - Err(_) => ty::Const::new_var(self.tcx, self.root_const_var(vid)), - } + fn shallow_resolve_const_var(&self, vid: ty::ConstVid) -> ty::Const<'tcx> { + self.shallow_resolve_const_var(vid) } - fn opportunistic_resolve_lt_var(&self, vid: ty::RegionVid) -> ty::Region<'tcx> { - self.inner.borrow_mut().unwrap_region_constraints().opportunistic_resolve_var(self.tcx, vid) + fn shallow_resolve_region_var(&self, vid: ty::RegionVid) -> ty::Region<'tcx> { + self.inner + .borrow_mut() + .unwrap_region_constraints() + .shallow_resolve_region_var(self.tcx, vid) } fn ty_or_const_infer_var_changed(&self, var: TyOrConstInferVar) -> bool { @@ -278,11 +275,11 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { self.shallow_resolve_const(ct) } - fn resolve_vars_if_possible(&self, value: T) -> T + fn deeply_resolve_ignoring_regions(&self, value: T) -> T where T: TypeFoldable>, { - self.resolve_vars_if_possible(value) + self.deeply_resolve_ignoring_regions(value) } fn probe(&self, probe: impl FnOnce() -> T) -> T { diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index ad469ac8f86d3..25e55601c628b 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1223,7 +1223,7 @@ impl<'tcx> InferCtxt<'tcx> { } pub fn ty_to_string(&self, t: Ty<'tcx>) -> String { - self.resolve_vars_if_possible(t).to_string() + self.deeply_resolve_ignoring_regions(t).to_string() } /// If `TyVar(vid)` resolves to a type, return that type. Else, return the @@ -1247,6 +1247,25 @@ impl<'tcx> InferCtxt<'tcx> { } } + /// Resolve a type variable. Resolving means the following: + /// + /// - If a `Ty` is a rigid type (like, an integer, or some ADT), do nothing. + /// - If a `Ty` is a type infer variable, but has been equated with an actual type, + /// return that type. + /// - If a `Ty` is an int or float infer variable, and has been equated with an integer + /// or floating point type, return that type. + /// - If a `Ty` is any kind of infer variable that has been equated, but not yet with a rigid + /// type, then this set of equated variables forms an equivalence class. One of the variables + /// in that equivalent class is said to be the root variable, and resolving makes sure to + /// consistently return this root variable. This is beneficial for caching. + /// This behavior, of returning roots, changed in . + /// + /// Otherwise, resolving simply does nothing. + /// + /// The "shallow" part of the name refers to the fact that types may themselves contain more + /// type variables. e.g. The field types of a struct. `shallow_resolve` does not recurse into + /// these nested variables. If that's what you want, use [`deeply_resolve_ignoring_regions`](Self::deeply_resolve_ignoring_regions), + /// or better [`deeply_resolve`](rustc_type_ir::deeply_resolve), if you can, which *does* resolve regions. pub fn shallow_resolve(&self, ty: Ty<'tcx>) -> Ty<'tcx> { if let ty::Infer(v) = *ty.kind() { match v { @@ -1312,6 +1331,8 @@ impl<'tcx> InferCtxt<'tcx> { } } + /// See docs on [`shallow_resolve`](Self::shallow_resolve) for more explanation. + /// It's the same, but for consts. pub fn shallow_resolve_const(&self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { match ct.kind() { ty::ConstKind::Infer(infer_ct) => match infer_ct { @@ -1338,6 +1359,8 @@ impl<'tcx> InferCtxt<'tcx> { } } + /// See docs on [`shallow_resolve`](Self::shallow_resolve) for more explanation. + /// It's the same, but for terms (types or consts). pub fn shallow_resolve_term(&self, term: ty::Term<'tcx>) -> ty::Term<'tcx> { match term.kind() { ty::TermKind::Ty(ty) => self.shallow_resolve(ty).into(), @@ -1372,9 +1395,27 @@ impl<'tcx> InferCtxt<'tcx> { self.inner.borrow_mut().const_unification_table().find(var).vid } + /// Resolves a const var to a rigid const, if it was constrained to one, + /// or else the root const var in the unification table. + pub fn shallow_resolve_const_var(&self, vid: ty::ConstVid) -> ty::Const<'tcx> { + match self.try_resolve_const_var(vid) { + Ok(ct) => ct, + Err(_) => ty::Const::new_var(self.tcx, self.root_const_var(vid)), + } + } + + /// Resolves a type var to a rigid type, if it was constrained to one, + /// or else the root type var in the unification table. + pub fn shallow_resolve_ty_var(&self, vid: ty::TyVid) -> Ty<'tcx> { + match self.try_resolve_ty_var(vid) { + Ok(ty) => ty, + Err(_) => Ty::new_var(self.tcx, self.root_var(vid)), + } + } + /// Resolves an int var to a rigid int type, if it was constrained to one, /// or else the root int var in the unification table. - pub fn opportunistic_resolve_int_var(&self, vid: ty::IntVid) -> Ty<'tcx> { + pub fn shallow_resolve_int_var(&self, vid: ty::IntVid) -> Ty<'tcx> { let mut inner = self.inner.borrow_mut(); let value = inner.int_unification_table().probe_value(vid); match value { @@ -1386,9 +1427,9 @@ impl<'tcx> InferCtxt<'tcx> { } } - /// Resolves a float var to a rigid int type, if it was constrained to one, + /// Resolves a float var to a rigid type, if it was constrained to one, /// or else the root float var in the unification table. - pub fn opportunistic_resolve_float_var(&self, vid: ty::FloatVid) -> Ty<'tcx> { + pub fn shallow_resolve_float_var(&self, vid: ty::FloatVid) -> Ty<'tcx> { let mut inner = self.inner.borrow_mut(); let value = inner.float_unification_table().probe_value(vid); match value { @@ -1399,13 +1440,13 @@ impl<'tcx> InferCtxt<'tcx> { } } - /// Where possible, replaces type/const variables in - /// `value` with their final value. Note that region variables - /// are unaffected. If a type/const variable has not been unified, it - /// is left as is. This is an idempotent operation that does - /// not affect inference state in any way and so you can do it - /// at will. - pub fn resolve_vars_if_possible(&self, value: T) -> T + /// If a type/const variable has not (yet) been unified, it is left as is. + /// + /// This is an idempotent operation that does not affect inference state in any way, + /// which means it's safe to call this function at will. + /// + /// Region variables are unaffected. + pub fn deeply_resolve_ignoring_regions(&self, value: T) -> T where T: TypeFoldable>, { @@ -1415,7 +1456,7 @@ impl<'tcx> InferCtxt<'tcx> { if !value.has_non_region_infer() { return value; } - let mut r = resolve::OpportunisticVarResolver::new(self); + let mut r = resolve::DeepResolverIgnoringRegions::new(self); value.fold_with(&mut r) } @@ -1447,8 +1488,11 @@ impl<'tcx> InferCtxt<'tcx> { /// /// This method is idempotent, but it not typically not invoked /// except during the writeback phase. - pub fn fully_resolve>>(&self, value: T) -> FixupResult { - match resolve::fully_resolve(self, value) { + pub fn deeply_resolve_via_region_graph>>( + &self, + value: T, + ) -> FixupResult { + match resolve::deeply_resolve_via_region_graph(self, value) { Ok(value) => { if value.has_non_region_infer() { bug!("`{value:?}` is not fully resolved"); diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index 70423ca7da1be..38a430931b250 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -166,7 +166,7 @@ impl<'tcx> InferCtxt<'tcx> { } else if let Some(res) = process(b, a) { res } else { - let (a, b) = self.resolve_vars_if_possible((a, b)); + let (a, b) = self.deeply_resolve_ignoring_regions((a, b)); Err(TypeError::Sorts(ExpectedFound::new(a, b))) } } diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs index 473b476ce8697..20bf987e07d0c 100644 --- a/compiler/rustc_infer/src/infer/outlives/mod.rs +++ b/compiler/rustc_infer/src/infer/outlives/mod.rs @@ -36,7 +36,7 @@ impl<'tcx> InferCtxt<'tcx> { /// Process the region constraints and return any errors that /// result. After this, no more unification operations should be /// done -- or the compiler will panic -- but it is legal to use - /// `resolve_vars_if_possible` as well as `fully_resolve`. + /// `deeply_resolve_ignoring_regions` as well as `fully_resolve`. /// /// Don't call this directly unless you know what you're doing. /// You probably want to use `resolve_regions` instead. diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index dbe85e5315500..bc75f1eeb40e1 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -66,7 +66,7 @@ use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::outlives::{Component, push_outlives_components}; use rustc_middle::ty::{ self, GenericArgKind, GenericArgsRef, PolyTypeOutlivesClause, Region, RegionVid, Ty, TyCtxt, - TypeVisitableExt, Upcast, eager_resolve_vars, + TypeVisitableExt, Upcast, }; use rustc_span::Span; use rustc_type_ir::region_constraint::{self, LeafRegionConstraint}; @@ -340,6 +340,8 @@ impl<'tcx> InferCtxt<'tcx> { outlives_env: &OutlivesEnvironment<'tcx>, span: Span, ) { + use rustc_type_ir::InferCtxtLike; + assert!(!self.in_snapshot(), "cannot process registered region obligations in a snapshot"); if self.tcx.assumptions_on_binders() { @@ -366,7 +368,12 @@ impl<'tcx> InferCtxt<'tcx> { // `TypeOutlives` is structural, so we should try to opportunistically resolve all // region vids before processing regions, so we have a better chance to match clauses // in our param-env. - let (sup_type, sub_region) = eager_resolve_vars(self, (sup_type, sub_region)); + // + // We *want* this folder to live in `rustc_type_ir`. Our best way to call into it is + // through `InferCtxtLike` and it is not defined as an inherent method on `InferCtxt`. + #[allow(rustc::usage_of_type_ir_traits)] + let (sup_type, sub_region) = + self.deeply_resolve_via_unification_table((sup_type, sub_region)); if self.tcx.sess.opts.unstable_opts.higher_ranked_assumptions && outlives_env diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index 240b288728832..c17933d2629a5 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -672,7 +672,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { /// Resolves a region var to its value in the unification table, if it exists. /// Otherwise, it is resolved to the root `ReVar` in the table. - pub fn opportunistic_resolve_var( + pub fn shallow_resolve_region_var( &mut self, tcx: TyCtxt<'tcx>, vid: ty::RegionVid, @@ -685,7 +685,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { } } - pub fn probe_value( + pub fn try_resolve_region_var( &mut self, vid: ty::RegionVid, ) -> Result, ty::UniverseIndex> { @@ -743,7 +743,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { | ty::ReEarlyParam(..) | ty::ReError(_) => ty::UniverseIndex::ROOT, ty::RePlaceholder(placeholder) => placeholder.universe, - ty::ReVar(vid) => match self.probe_value(vid) { + ty::ReVar(vid) => match self.try_resolve_region_var(vid) { Ok(value) => self.universe(value), Err(universe) => universe, }, diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs index db4f313903a5a..1ced1b336c817 100644 --- a/compiler/rustc_infer/src/infer/resolve.rs +++ b/compiler/rustc_infer/src/infer/resolve.rs @@ -9,28 +9,28 @@ use super::{FixupError, FixupResult, InferCtxt}; use crate::infer::TyOrConstInferVar; /////////////////////////////////////////////////////////////////////////// -// OPPORTUNISTIC VAR RESOLVER +// DEEP VAR RESOLVER -/// The opportunistic resolver can be used at any time. It simply replaces +/// The type and const resolver can be used at any time. It simply replaces /// type/const variables that have been unified with the things they have /// been unified with (similar to `shallow_resolve`, but deep). This is /// useful for printing messages etc but also required at various /// points for correctness. -pub struct OpportunisticVarResolver<'a, 'tcx> { +pub struct DeepResolverIgnoringRegions<'a, 'tcx> { infcx: &'a InferCtxt<'tcx>, /// We're able to use a cache here as the folder does /// not have any mutable state. cache: DelayedMap, Ty<'tcx>>, } -impl<'a, 'tcx> OpportunisticVarResolver<'a, 'tcx> { +impl<'a, 'tcx> DeepResolverIgnoringRegions<'a, 'tcx> { #[inline] pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self { - OpportunisticVarResolver { infcx, cache: Default::default() } + DeepResolverIgnoringRegions { infcx, cache: Default::default() } } } -impl<'a, 'tcx> TypeFolder> for OpportunisticVarResolver<'a, 'tcx> { +impl<'a, 'tcx> TypeFolder> for DeepResolverIgnoringRegions<'a, 'tcx> { fn cx(&self) -> TyCtxt<'tcx> { self.infcx.tcx } @@ -67,24 +67,24 @@ impl<'a, 'tcx> TypeFolder> for OpportunisticVarResolver<'a, 'tcx> { } } -/// The opportunistic region resolver opportunistically resolves regions -/// variables to the variable with the least variable id. It is used when -/// normalizing projections to avoid hitting the recursion limit by creating -/// many versions of a predicate for types that in the end have to unify. +/// The region resolver resolves region variables to the variable with the +/// least variable id. It is used when normalizing projections to avoid +/// hitting the recursion limit by creating many versions of a predicate +/// for types that in the end have to unify. /// /// If you want to resolve type and const variables as well, call -/// [InferCtxt::resolve_vars_if_possible] first. -pub struct OpportunisticRegionResolver<'a, 'tcx> { +/// [InferCtxt::deeply_resolve_ignoring_regions] first. +pub struct DeepRegionResolver<'a, 'tcx> { infcx: &'a InferCtxt<'tcx>, } -impl<'a, 'tcx> OpportunisticRegionResolver<'a, 'tcx> { +impl<'a, 'tcx> DeepRegionResolver<'a, 'tcx> { pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self { - OpportunisticRegionResolver { infcx } + DeepRegionResolver { infcx } } } -impl<'a, 'tcx> TypeFolder> for OpportunisticRegionResolver<'a, 'tcx> { +impl<'a, 'tcx> TypeFolder> for DeepRegionResolver<'a, 'tcx> { fn cx(&self) -> TyCtxt<'tcx> { self.infcx.tcx } @@ -104,7 +104,7 @@ impl<'a, 'tcx> TypeFolder> for OpportunisticRegionResolver<'a, 'tcx .inner .borrow_mut() .unwrap_region_constraints() - .opportunistic_resolve_var(TypeFolder::cx(self), vid), + .shallow_resolve_region_var(TypeFolder::cx(self), vid), _ => r, } } @@ -124,7 +124,7 @@ impl<'a, 'tcx> TypeFolder> for OpportunisticRegionResolver<'a, 'tcx /// Full type resolution replaces all type and region variables with /// their concrete results. If any variable cannot be replaced (never unified, etc) /// then an `Err` result is returned. -pub fn fully_resolve<'tcx, T>(infcx: &InferCtxt<'tcx>, value: T) -> FixupResult +pub fn deeply_resolve_via_region_graph<'tcx, T>(infcx: &InferCtxt<'tcx>, value: T) -> FixupResult where T: TypeFoldable>, { diff --git a/compiler/rustc_infer/src/infer/snapshot/fudge.rs b/compiler/rustc_infer/src/infer/snapshot/fudge.rs index 2ce98b7541afa..98ac3f4376c2c 100644 --- a/compiler/rustc_infer/src/infer/snapshot/fudge.rs +++ b/compiler/rustc_infer/src/infer/snapshot/fudge.rs @@ -111,7 +111,7 @@ impl<'tcx> InferCtxt<'tcx> { // going to be popped, so we will have to // eliminate any references to them. let snapshot_vars = SnapshotVarData::new(self, variable_lengths); - Ok((snapshot_vars, self.resolve_vars_if_possible(value))) + Ok((snapshot_vars, self.deeply_resolve_ignoring_regions(value))) })?; // At this point, we need to replace any of the now-popped diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 1ff2a2cb1a404..7452e3e08ade9 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -135,6 +135,88 @@ trait UnusedDelimLint { is_kw: bool, ); + /// Returns whether the outer braces of a single-expression function/method + /// argument block can be removed. + /// + /// In Rust 2024, `{ expr }` can drop tail-expression temporaries before the + /// call starts. Removing the block may extend those temporaries, so lint only + /// expression forms that are harmless here. + fn expr_allows_remove_arg_block(expr: &ast::Expr) -> bool { + use ast::ExprKind::*; + + match &expr.peel_parens().kind { + Lit(_) | IncludedBytes(_) | Path(..) => true, + Unary(_, expr) + | Cast(expr, _) + | Type(expr, _) + | Use(expr, _) + | Await(expr, _) + | Try(expr) + | Move(expr, _) + | AddrOf(_, _, expr) + | UnsafeBinderCast(_, expr, _) => Self::expr_allows_remove_arg_block(expr), + Array(exprs) | Tup(exprs) => { + exprs.iter().all(|expr| Self::expr_allows_remove_arg_block(expr)) + } + Binary(_, lhs, rhs) | Assign(lhs, rhs, _) | AssignOp(_, lhs, rhs) => { + Self::expr_allows_remove_arg_block(lhs) && Self::expr_allows_remove_arg_block(rhs) + } + Index(base, index, _) => { + Self::expr_allows_remove_arg_block(base) + && Self::expr_allows_remove_arg_block(index) + } + Range(start, end, _) => { + start.as_ref().is_none_or(|expr| Self::expr_allows_remove_arg_block(expr)) + && end.as_ref().is_none_or(|expr| Self::expr_allows_remove_arg_block(expr)) + } + Struct(expr) => { + expr.fields.iter().all(|field| Self::expr_allows_remove_arg_block(&field.expr)) + && match &expr.rest { + ast::StructRest::Base(expr) => Self::expr_allows_remove_arg_block(expr), + ast::StructRest::Rest(_) | ast::StructRest::None => true, + ast::StructRest::NoneWithError(_) => false, + } + } + Repeat(expr, _) => Self::expr_allows_remove_arg_block(expr), + ConstBlock(_) + | If(..) + | While(..) + | ForLoop { .. } + | Loop(..) + | Match(..) + | Closure(_) + | Block(..) + | Gen(..) + | TryBlock(..) + | Break(..) + | Continue(_) + | Ret(_) + | InlineAsm(_) + | OffsetOf(..) + | Yield(_) + | Yeet(_) + | Paren(_) + | Become(_) => true, + Call(..) | MethodCall(_) | Let(..) | Field(..) | MacCall(_) | FormatArgs(_) => false, + // `direct_const_arg!()` is invalid in function/method argument position. + DirectConstArg(_) => false, + // don't lint for placeholder/error-recovery + Underscore | Err(_) | Dummy => false, + } + } + + /// Returns whether `{ expr }` must be kept in function/method argument + /// position to avoid changing temporary lifetime semantics. + fn needs_arg_block_to_preserve_temporaries( + ctx: UnusedDelimsCtx, + arg_block: &ast::Expr, + expr: &ast::Expr, + ) -> bool { + matches!(ctx, UnusedDelimsCtx::FunctionArg | UnusedDelimsCtx::MethodArg) + && arg_block.span.edition().at_least_rust_2024() + && !Self::expr_allows_remove_arg_block(expr) + } + fn is_expr_delims_necessary( inner: &ast::Expr, ctx: UnusedDelimsCtx, @@ -1098,6 +1180,7 @@ impl UnusedDelimLint for UnusedBraces { // lock guard, before the loop starts. && !(ctx == UnusedDelimsCtx::ForIterExpr && value.span.edition().at_least_rust_2024()) + && !Self::needs_arg_block_to_preserve_temporaries(ctx, value, expr) && (ctx != UnusedDelimsCtx::AnonConst || (matches!(expr.kind, ast::ExprKind::Lit(_)) && !expr.span.from_expansion())) diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index dc4a41ace6b88..9a2e86577fa62 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1,8 +1,10 @@ use std::borrow::Borrow; +use std::cell::RefCell; use std::collections::hash_map::Entry; use std::fs::File; use std::io::{Read, Seek, Write}; use std::path::{Path, PathBuf}; +use std::rc::Rc; use std::sync::Arc; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; @@ -29,7 +31,7 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder, opaque}; use rustc_session::config::mitigation_coverage::DeniedPartialMitigation; use rustc_session::config::{OptLevel, TargetModifier}; use rustc_span::def_id::CRATE_MOD_ID; -use rustc_span::hygiene::HygieneEncodeContext; +use rustc_span::hygiene::{HygieneEncodeContext, raw_encode_syntax_context}; use rustc_span::{ ByteSymbol, ExternalSource, FileName, SourceFile, SpanData, SpanEncoder, StableSourceFileId, Symbol, SyntaxContext, sym, @@ -66,7 +68,7 @@ pub(super) struct EncodeContext<'a, 'tcx> { // order of `SourceFiles`, and encoded inside `Span`s. required_source_files: Option>, is_proc_macro: bool, - hygiene_ctxt: &'a HygieneEncodeContext, + hygiene_ctxt: Rc>, // Used for both `Symbol`s and `ByteSymbol`s. symbol_index_table: FxHashMap, } @@ -156,7 +158,7 @@ impl<'a, 'tcx> SpanEncoder for EncodeContext<'a, 'tcx> { } fn encode_syntax_context(&mut self, syntax_context: SyntaxContext) { - rustc_span::hygiene::raw_encode_syntax_context(syntax_context, self.hygiene_ctxt, self); + raw_encode_syntax_context(syntax_context, Rc::clone(&self.hygiene_ctxt), self) } fn encode_expn_id(&mut self, expn_id: ExpnId) { @@ -165,7 +167,7 @@ impl<'a, 'tcx> SpanEncoder for EncodeContext<'a, 'tcx> { // data from the corresponding crate's metadata. // FIXME(#43047) FIXME(#74731) We may eventually want to avoid relying on external // metadata from proc-macro crates. - self.hygiene_ctxt.schedule_expn_data_for_encoding(expn_id); + self.hygiene_ctxt.borrow_mut().schedule_expn_data_for_encoding(expn_id); } expn_id.krate.encode(self); expn_id.local_id.encode(self); @@ -1966,14 +1968,17 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let mut expn_data_table: TableBuilder<_, _> = Default::default(); let mut expn_hash_table: TableBuilder<_, _> = Default::default(); - self.hygiene_ctxt.encode( + HygieneEncodeContext::encode( + &Rc::clone(&self.hygiene_ctxt), &mut (&mut *self, &mut syntax_contexts, &mut expn_data_table, &mut expn_hash_table), |(this, syntax_contexts, _, _), index, ctxt_data| { syntax_contexts.set_some(index, this.lazy(ctxt_data)); }, |(this, _, expn_data_table, expn_hash_table), index, expn_data, hash| { if let Some(index) = index.as_local() { - expn_data_table.set_some(index.as_raw(), this.lazy(expn_data)); + expn_data_table + .set_some(index.as_raw(), this.lazy(expn_data.expect("local expn"))); + expn_hash_table.set_some(index.as_raw(), this.lazy(hash)); } }, @@ -2559,8 +2564,6 @@ fn with_encode_metadata_header( let required_source_files = Some(FxIndexSet::default()); drop(source_map_files); - let hygiene_ctxt = HygieneEncodeContext::default(); - let mut ecx = EncodeContext { opaque: encoder, tcx, @@ -2574,7 +2577,7 @@ fn with_encode_metadata_header( interpret_allocs: Default::default(), required_source_files, is_proc_macro: tcx.crate_types().contains(&CrateType::ProcMacro), - hygiene_ctxt: &hygiene_ctxt, + hygiene_ctxt: Default::default(), symbol_index_table: Default::default(), }; diff --git a/compiler/rustc_middle/src/hooks.rs b/compiler/rustc_middle/src/hooks.rs index 7a69f58d52fae..df95bd6149e47 100644 --- a/compiler/rustc_middle/src/hooks.rs +++ b/compiler/rustc_middle/src/hooks.rs @@ -106,7 +106,7 @@ declare_hooks! { hook build_mir_inner_impl(def: LocalDefId) -> mir::Body<'tcx>; /// Serializes all eligible query return values into the on-disk cache. - hook encode_query_values(encoder: &mut CacheEncoder<'_, 'tcx>) -> (); + hook encode_query_values(encoder: &mut CacheEncoder<'tcx>) -> (); } #[cold] diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index d743c5dcc7e43..1fa0aa421d584 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -1,4 +1,6 @@ +use std::cell::RefCell; use std::collections::hash_map::Entry; +use std::rc::Rc; use std::sync::Arc; use std::{fmt, mem}; @@ -16,6 +18,7 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_session::Session; use rustc_span::hygiene::{ ExpnId, HygieneDecodeContext, HygieneEncodeContext, SyntaxContext, SyntaxContextKey, + raw_encode_syntax_context, }; use rustc_span::{ BlobDecoder, BytePos, ByteSymbol, CachingSourceMapView, ExpnData, ExpnHash, RelativeBytePos, @@ -223,8 +226,6 @@ impl OnDiskCache { (file_to_file_index, file_index_to_stable_id) }; - let hygiene_encode_context = HygieneEncodeContext::default(); - let mut encoder = CacheEncoder { tcx, encoder, @@ -233,7 +234,7 @@ impl OnDiskCache { interpret_allocs: Default::default(), caching_source_map_view: CachingSourceMapView::new(tcx.sess.source_map()), file_to_file_index, - hygiene_context: &hygiene_encode_context, + hygiene_context: Default::default(), symbol_index_table: Default::default(), query_values_index: Default::default(), side_effects_index: Default::default(), @@ -278,7 +279,8 @@ impl OnDiskCache { // Encode all hygiene data (`SyntaxContextData` and `ExpnData`) from the current // session. - hygiene_encode_context.encode( + HygieneEncodeContext::encode( + &Rc::clone(&encoder.hygiene_context), &mut encoder, |encoder, index, ctxt_data| { let pos = AbsoluteBytePos::new(encoder.position()); @@ -288,7 +290,7 @@ impl OnDiskCache { |encoder, expn_id, data, hash| { if expn_id.krate == LOCAL_CRATE { let pos = AbsoluteBytePos::new(encoder.position()); - encoder.encode_tagged(TAG_EXPN_DATA, data); + encoder.encode_tagged(TAG_EXPN_DATA, data.expect("local expn")); expn_data.insert(hash, pos); } else { foreign_expn_data.insert(hash, expn_id.local_id.as_u32()); @@ -774,7 +776,7 @@ impl_ref_decoder! {<'tcx> //- ENCODING ------------------------------------------------------------------- /// An encoder that can write to the incremental compilation cache. -pub struct CacheEncoder<'a, 'tcx> { +pub struct CacheEncoder<'tcx> { tcx: TyCtxt<'tcx>, encoder: FileEncoder<'static>, type_shorthands: FxHashMap, usize>, @@ -782,7 +784,7 @@ pub struct CacheEncoder<'a, 'tcx> { interpret_allocs: FxIndexSet, caching_source_map_view: CachingSourceMapView<'tcx>, file_to_file_index: FxHashMap<*const SourceFile, SourceFileIndex>, - hygiene_context: &'a HygieneEncodeContext, + hygiene_context: Rc>, // Used for both `Symbol`s and `ByteSymbol`s. symbol_index_table: FxHashMap, @@ -790,14 +792,14 @@ pub struct CacheEncoder<'a, 'tcx> { side_effects_index: Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>, } -impl<'a, 'tcx> fmt::Debug for CacheEncoder<'a, 'tcx> { +impl<'tcx> fmt::Debug for CacheEncoder<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // Add more details here if/when necessary. f.write_str("CacheEncoder") } } -impl<'a, 'tcx> CacheEncoder<'a, 'tcx> { +impl<'tcx> CacheEncoder<'tcx> { #[inline] fn source_file_index(&mut self, source_file: Arc) -> SourceFileIndex { self.file_to_file_index[&(&raw const *source_file)] @@ -866,13 +868,13 @@ impl<'a, 'tcx> CacheEncoder<'a, 'tcx> { } } -impl<'a, 'tcx> SpanEncoder for CacheEncoder<'a, 'tcx> { +impl<'tcx> SpanEncoder for CacheEncoder<'tcx> { fn encode_syntax_context(&mut self, syntax_context: SyntaxContext) { - rustc_span::hygiene::raw_encode_syntax_context(syntax_context, self.hygiene_context, self); + raw_encode_syntax_context(syntax_context, Rc::clone(&self.hygiene_context), self); } fn encode_expn_id(&mut self, expn_id: ExpnId) { - self.hygiene_context.schedule_expn_data_for_encoding(expn_id); + self.hygiene_context.borrow_mut().schedule_expn_data_for_encoding(expn_id); expn_id.expn_hash().encode(self); } @@ -944,7 +946,7 @@ impl<'a, 'tcx> SpanEncoder for CacheEncoder<'a, 'tcx> { } } -impl<'a, 'tcx> TyEncoder<'tcx> for CacheEncoder<'a, 'tcx> { +impl<'tcx> TyEncoder<'tcx> for CacheEncoder<'tcx> { const CLEAR_CROSS_CRATE: bool = false; #[inline] @@ -976,7 +978,7 @@ macro_rules! encoder_methods { } } -impl<'a, 'tcx> Encoder for CacheEncoder<'a, 'tcx> { +impl<'tcx> Encoder for CacheEncoder<'tcx> { encoder_methods! { emit_usize(usize); emit_u128(u128); @@ -999,8 +1001,8 @@ impl<'a, 'tcx> Encoder for CacheEncoder<'a, 'tcx> { // is used when a `CacheEncoder` having an `opaque::FileEncoder` is passed to `Encodable::encode`. // Unfortunately, we have to manually opt into specializations this way, given how `CacheEncoder` // and the encoding traits currently work. -impl<'a, 'tcx> Encodable> for [u8] { - fn encode(&self, e: &mut CacheEncoder<'a, 'tcx>) { +impl<'tcx> Encodable> for [u8] { + fn encode(&self, e: &mut CacheEncoder<'tcx>) { self.encode(&mut e.encoder); } } diff --git a/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs index 6047966248bb2..f0f0ebaf2b3bb 100644 --- a/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs @@ -322,7 +322,7 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { ty::Infer(i) => match i { ty::TyVar(vid) => { debug_assert_eq!( - self.delegate.opportunistic_resolve_ty_var(vid), + self.delegate.shallow_resolve_ty_var(vid), t, "ty vid should have been resolved fully before canonicalization" ); @@ -339,7 +339,7 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { } ty::IntVar(vid) => { debug_assert_eq!( - self.delegate.opportunistic_resolve_int_var(vid), + self.delegate.shallow_resolve_int_var(vid), t, "ty vid should have been resolved fully before canonicalization" ); @@ -347,7 +347,7 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { } ty::FloatVar(vid) => { debug_assert_eq!( - self.delegate.opportunistic_resolve_float_var(vid), + self.delegate.shallow_resolve_float_var(vid), t, "ty vid should have been resolved fully before canonicalization" ); @@ -489,7 +489,7 @@ impl, I: Interner> TypeFolder for Canonicaliz ty::ReVar(vid) => { debug_assert_eq!( - self.delegate.opportunistic_resolve_lt_var(vid), + self.delegate.shallow_resolve_region_var(vid), r, "region vid should have been resolved fully before canonicalization" ); @@ -501,7 +501,7 @@ impl, I: Interner> TypeFolder for Canonicaliz )) } CanonicalizeMode::Response { .. } => { - CanonicalVarKind::Region(self.delegate.universe_of_lt(vid).unwrap()) + CanonicalVarKind::Region(self.delegate.universe_of_region(vid).unwrap()) } } } @@ -534,7 +534,7 @@ impl, I: Interner> TypeFolder for Canonicaliz ty::ConstKind::Infer(i) => match i { ty::InferConst::Var(vid) => { debug_assert_eq!( - self.delegate.opportunistic_resolve_ct_var(vid), + self.delegate.shallow_resolve_const_var(vid), c, "const vid should have been resolved fully before canonicalization" ); @@ -544,7 +544,7 @@ impl, I: Interner> TypeFolder for Canonicaliz CanonicalVarKind::Const(ty::UniverseIndex::ROOT) } CanonicalizeMode::Response { .. } => { - CanonicalVarKind::Const(self.delegate.universe_of_ct(vid).unwrap()) + CanonicalVarKind::Const(self.delegate.universe_of_const(vid).unwrap()) } } } diff --git a/compiler/rustc_next_trait_solver/src/canonical/mod.rs b/compiler/rustc_next_trait_solver/src/canonical/mod.rs index 0d8620c3614a2..c60e6ee246273 100644 --- a/compiler/rustc_next_trait_solver/src/canonical/mod.rs +++ b/compiler/rustc_next_trait_solver/src/canonical/mod.rs @@ -19,7 +19,7 @@ use rustc_type_ir::relate::{ }; use rustc_type_ir::{ self as ty, Canonical, CanonicalVarKind, CanonicalVarValues, InferCtxtLike, Interner, Region, - TypeFoldable, TypingMode, TypingModeEqWrapper, eager_resolve_vars, + TypeFoldable, TypingMode, TypingModeEqWrapper, }; use thin_vec::ThinVec; use tracing::instrument; @@ -568,7 +568,7 @@ where { let var_values = CanonicalVarValues { var_values: delegate.cx().mk_args(var_values) }; let state = inspect::State { var_values, data }; - let state = eager_resolve_vars(&**delegate, state); + let state = delegate.deeply_resolve_via_unification_table(state); Canonicalizer::canonicalize_response(delegate, max_input_universe, state) } diff --git a/compiler/rustc_next_trait_solver/src/normalize.rs b/compiler/rustc_next_trait_solver/src/normalize.rs index 1fd62213b735a..ab3a92da4ba54 100644 --- a/compiler/rustc_next_trait_solver/src/normalize.rs +++ b/compiler/rustc_next_trait_solver/src/normalize.rs @@ -3,7 +3,7 @@ use std::fmt::Debug; use rustc_type_ir::inherent::*; use rustc_type_ir::{ self as ty, AliasTerm, Binder, FallibleTypeFolder, InferCtxtLike, Interner, PredicateProxy, - TypeFoldable, TypeSuperFoldable, TypeVisitableExt, UniverseIndex, eager_resolve_vars, + TypeFoldable, TypeSuperFoldable, TypeVisitableExt, UniverseIndex, }; use tracing::instrument; @@ -139,8 +139,8 @@ where if self.cx().renormalize_rigid_aliases() && orig_is_rigid == ty::IsRigid::Yes { // find out missing typing env change. - let original = eager_resolve_vars(infcx, original); - let normalized = eager_resolve_vars(infcx, normalized); + let original = infcx.deeply_resolve_via_unification_table(original); + let normalized = infcx.deeply_resolve_via_unification_table(normalized); assert_eq!(original, normalized, "rigid alias is further normalized"); } Ok(normalized) @@ -189,8 +189,8 @@ where if self.cx().renormalize_rigid_aliases() && orig_is_rigid == ty::IsRigid::Yes { // find out missing typing env change. - let original = eager_resolve_vars(infcx, original); - let normalized = eager_resolve_vars(infcx, normalized); + let original = infcx.deeply_resolve_via_unification_table(original); + let normalized = infcx.deeply_resolve_via_unification_table(normalized); assert_eq!(original, normalized, "rigid alias is further normalized"); } diff --git a/compiler/rustc_next_trait_solver/src/placeholder.rs b/compiler/rustc_next_trait_solver/src/placeholder.rs index e24037e2da7cd..84811a101fb11 100644 --- a/compiler/rustc_next_trait_solver/src/placeholder.rs +++ b/compiler/rustc_next_trait_solver/src/placeholder.rs @@ -248,7 +248,7 @@ where fn fold_region(&mut self, r0: Region) -> Region { let r1 = match r0.kind() { - ty::ReVar(vid) => self.infcx.opportunistic_resolve_lt_var(vid), + ty::ReVar(vid) => self.infcx.shallow_resolve_region_var(vid), _ => r0, }; diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index 30e9c1a84c4ad..485568850bee0 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -503,7 +503,7 @@ where // Vars that show up in the rest of the goal substs may have been constrained by // normalizing the self type as well, since type variables are not uniquified. - let goal = self.resolve_vars_if_possible(goal); + let goal = self.deeply_resolve_ignoring_regions(goal); if self.typing_mode().is_coherence() && let Ok(candidate) = self.consider_coherence_unknowable_candidate(goal) diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index ae5cf61aac91e..61cd8e46d8816 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -19,8 +19,7 @@ use rustc_type_ir::solve::{ use rustc_type_ir::{ self as ty, CanonicalVarValues, ClauseKind, InferCtxtLike, Interner, MayBeErased, OpaqueTypeKey, PredicateKind, PredicateProxy, Region, RegionVid, TypeFoldable, - TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, - eager_resolve_vars, max_universe, + TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, max_universe, }; use thin_vec::ThinVec; use tracing::{Level, debug, instrument, trace, warn}; @@ -659,7 +658,9 @@ where // so we only canonicalize the lookup table and ignore // duplicate entries. let opaque_types = self.delegate.clone_opaque_types_lookup_table(); - let (goal, opaque_types) = eager_resolve_vars(&**self.delegate, (goal, opaque_types)); + + let (goal, opaque_types) = + self.delegate.deeply_resolve_via_unification_table((goal, opaque_types)); let typing_mode = self.typing_mode(); let step_kind = self.step_kind_for_source(source); @@ -1098,7 +1099,7 @@ where } ty::TermKind::Const(ct) => { if let ty::ConstKind::Infer(ty::InferConst::Var(vid)) = ct.kind() { - self.delegate.universe_of_ct(vid).unwrap() + self.delegate.universe_of_const(vid).unwrap() } else { return false; } @@ -1165,7 +1166,7 @@ where return ControlFlow::Break(()); } - self.check_nameable(self.delegate.universe_of_ct(vid).unwrap()) + self.check_nameable(self.delegate.universe_of_const(vid).unwrap()) } ty::ConstKind::Placeholder(p) => self.check_nameable(p.universe()), _ => { @@ -1300,11 +1301,11 @@ where }) } - pub(super) fn resolve_vars_if_possible(&self, value: T) -> T + pub(super) fn deeply_resolve_ignoring_regions(&self, value: T) -> T where T: TypeFoldable, { - self.delegate.resolve_vars_if_possible(value) + self.delegate.deeply_resolve_ignoring_regions(value) } pub(super) fn shallow_resolve(&self, ty: I::Ty) -> I::Ty { @@ -1313,7 +1314,7 @@ where pub(super) fn eager_resolve_region(&self, r: Region) -> Region { if let ty::ReVar(vid) = r.kind() { - self.delegate.opportunistic_resolve_lt_var(vid) + self.delegate.shallow_resolve_region_var(vid) } else { r } @@ -1432,14 +1433,14 @@ where self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } None if self.cx().features().generic_const_args() => { - // HACK(khyperia): calling `resolve_vars_if_possible` here shouldn't be necessary, - // `try_evaluate_const` calls `resolve_vars_if_possible` already. However, we want + // HACK(khyperia): calling `deeply_resolve_ignoring_regions` here shouldn't be necessary, + // `try_evaluate_const` calls `deeply_resolve_ignoring_regions` already. However, we want // to check `has_non_region_infer` against the type with vars resolved (i.e. check // if there are vars we failed to resolve), so we need to call it again here. // Perhaps we could split EvaluateConstErr::HasGenericsOrInfers into HasGenerics and // HasInfers or something, make evaluate_const return that, and make this branch be // based on that, rather than checking `has_non_region_infer`. - if self.resolve_vars_if_possible(alias_const).has_non_region_infer() { + if self.deeply_resolve_ignoring_regions(alias_const).has_non_region_infer() { self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) } else { // Evaluation failed because the const was too generic or was an invalid type @@ -1604,8 +1605,9 @@ where let external_constraints = self.compute_external_query_constraints(certainty, normalization_nested_goals); - let (var_values, mut external_constraints) = - eager_resolve_vars(&**self.delegate, (self.var_values, external_constraints)); + let (var_values, mut external_constraints) = self + .delegate + .deeply_resolve_via_unification_table((self.var_values, external_constraints)); // Remove any trivial or duplicated region constraints once we've resolved regions let mut unique = HashSet::default(); @@ -1672,7 +1674,7 @@ where && let ty::RegionKind::ReVar(vid) = re.kind() // This is only safe if we call `eager_resolve_vars` beforehand, // which we do. - && self.delegate.universe_of_lt(vid).unwrap() + && self.delegate.universe_of_region(vid).unwrap() .can_name(max_universe(&**self.delegate, sup_re)) { vis.vars.contains(&vid) @@ -1772,7 +1774,7 @@ where param_env: I::ParamEnv, value: ty::Unnormalized, ) -> Result { - let value = self.delegate.resolve_vars_if_possible(value.skip_normalization()); + let value = self.delegate.deeply_resolve_ignoring_regions(value.skip_normalization()); if !self.cx().renormalize_rigid_aliases() && !value.has_non_rigid_aliases() { return Ok(value); @@ -1795,7 +1797,7 @@ where } }; - Ok((self.resolve_vars_if_possible(infer_term), normalization_was_ambiguous)) + Ok((self.deeply_resolve_ignoring_regions(infer_term), normalization_was_ambiguous)) }); value.try_fold_with(&mut folder) } @@ -1929,7 +1931,7 @@ pub(super) fn evaluate_root_goal_for_proof_tree, root_depth: usize, ) -> (Result, NoSolution>, inspect::GoalEvaluation) { let opaque_types = delegate.clone_opaque_types_lookup_table(); - let (goal, opaque_types) = eager_resolve_vars(&**delegate, (goal, opaque_types)); + let (goal, opaque_types) = delegate.deeply_resolve_via_unification_table((goal, opaque_types)); let typing_mode = delegate.typing_mode_raw().assert_not_erased(); let (orig_values, canonical_goal) = diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index 8d20bcf4c7a6d..10ee038005d8e 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -404,7 +404,7 @@ where // types from candidates. self.add_goal(GoalSource::TypeRelating, projection_goal)?; self.try_evaluate_added_goals()?; - Ok(self.resolve_vars_if_possible(normalized_term)) + Ok(self.deeply_resolve_ignoring_regions(normalized_term)) } else { Ok(term) } diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 51ec0bcbf5ec2..294c887b5062c 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -1114,7 +1114,7 @@ where return Ok(false); } match ecx.probe(|_| ProbeKind::ProjectionCompatibility).enter(|ecx| { - let target_projection = ecx.resolve_vars_if_possible(target_projection); + let target_projection = ecx.deeply_resolve_ignoring_regions(target_projection); ecx.enter_forall_with_assumptions( target_projection, param_env, @@ -1141,7 +1141,8 @@ where let source_principal = upcast_principal.unwrap(); let target_principal = bound.rebind(target_principal); // We might unify infer vars in previous iterations. - let target_principal = ecx.resolve_vars_if_possible(target_principal); + let target_principal = + ecx.deeply_resolve_ignoring_regions(target_principal); ecx.enter_forall_with_assumptions( target_principal, param_env, @@ -1176,7 +1177,8 @@ where }; // We might unify infer vars in previous iterations. - let target_projection = ecx.resolve_vars_if_possible(target_projection); + let target_projection = + ecx.deeply_resolve_ignoring_regions(target_projection); ecx.enter_forall_with_assumptions( target_projection, param_env, diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index cd7f422fb72f3..7da24f5251239 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -208,9 +208,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.check_rustc_allow_const_fn_unstable(hir_id, *first_span, span, target) } AttributeKind::Naked(..) => self.check_naked(hir_id, target), - AttributeKind::NonExhaustive(attr_span) => { - self.check_non_exhaustive(*attr_span, span, target, item) - } AttributeKind::MayDangle(attr_span) => self.check_may_dangle(hir_id, *attr_span), AttributeKind::Link(_, attr_span) => self.check_link(hir_id, *attr_span, target), AttributeKind::MacroExport { span, .. } => { @@ -293,6 +290,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { AttributeKind::NoMain => (), AttributeKind::NoMangle(..) => (), AttributeKind::NoStd { .. } => (), + AttributeKind::NonExhaustive(_) => (), AttributeKind::OnUnknown { .. } => (), AttributeKind::OnUnmatchedArgs { .. } => (), AttributeKind::Opaque => (), @@ -797,32 +795,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - /// Checks if the `#[non_exhaustive]` attribute on an `item` is valid. - fn check_non_exhaustive( - &self, - attr_span: Span, - span: Span, - target: Target, - item: Option<&'tcx Item<'tcx>>, - ) { - match target { - Target::Struct => { - if let hir::Item { - kind: hir::ItemKind::Struct(_, _, hir::VariantData::Struct { fields, .. }), - .. - } = item.unwrap() - && fields.iter().any(|f| f.default.is_some()) - { - self.dcx().emit_err(diagnostics::NonExhaustiveWithDefaultFieldValues { - attr_span, - defn_span: span, - }); - } - } - _ => {} - } - } - fn check_doc_alias_value(&self, span: Span, hir_id: HirId, target: Target, alias: Symbol) { if let Some(location) = match target { Target::AssocTy(_) => { diff --git a/compiler/rustc_passes/src/diagnostics.rs b/compiler/rustc_passes/src/diagnostics.rs index 5f99c4b133597..8b0ba0ab8f102 100644 --- a/compiler/rustc_passes/src/diagnostics.rs +++ b/compiler/rustc_passes/src/diagnostics.rs @@ -48,15 +48,6 @@ pub(crate) struct OuterCrateLevelAttrSuggestion { #[diag("crate-level attribute should be in the root module")] pub(crate) struct InnerCrateLevelAttr; -#[derive(Diagnostic)] -#[diag("`#[non_exhaustive]` can't be used to annotate items with default field values")] -pub(crate) struct NonExhaustiveWithDefaultFieldValues { - #[primary_span] - pub attr_span: Span, - #[label("this struct has default field values")] - pub defn_span: Span, -} - #[derive(Diagnostic)] #[diag("`#[doc(alias = \"...\")]` isn't allowed on {$location}")] pub(crate) struct DocAliasBadLocation<'a> { diff --git a/compiler/rustc_query_impl/src/incremental.rs b/compiler/rustc_query_impl/src/incremental.rs index 341c9f5e5068d..1a007ac55a4ea 100644 --- a/compiler/rustc_query_impl/src/incremental.rs +++ b/compiler/rustc_query_impl/src/incremental.rs @@ -19,19 +19,19 @@ fn all_inactive<'tcx, K>(state: &QueryState<'tcx, K>) -> bool { state.active.lock_shards().all(|shard| shard.is_empty()) } -pub(crate) fn encode_query_values<'tcx>(tcx: TyCtxt<'tcx>, encoder: &mut CacheEncoder<'_, 'tcx>) { +pub(crate) fn encode_query_values<'tcx>(tcx: TyCtxt<'tcx>, encoder: &mut CacheEncoder<'tcx>) { for_each_query_vtable!(CACHE_ON_DISK, tcx, |query| { encode_query_values_inner(tcx, query, encoder) }); } -fn encode_query_values_inner<'a, 'tcx, C, V>( +fn encode_query_values_inner<'tcx, C, V>( tcx: TyCtxt<'tcx>, query: &'tcx QueryVTable<'tcx, C>, - encoder: &mut CacheEncoder<'a, 'tcx>, + encoder: &mut CacheEncoder<'tcx>, ) where C: QueryCache>, - V: Erasable + Encodable>, + V: Erasable + Encodable>, { let _timer = tcx.prof.generic_activity_with_arg("encode_query_results_for", query.name); diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 4c8000c28f065..1fab7a37a9941 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -188,6 +188,7 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { &i.attrs, i.span, Target::MacroDef, + None, std::convert::identity, |_lint_id, _span, _kind| { // FIXME(jdonszelmann): emit lints here properly diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index fa0133a3c7fd8..3ca3fd0940f7f 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -24,7 +24,9 @@ // because getting it wrong can lead to nested `HygieneData::with` calls that // trigger runtime aborts. (Fortunately these are obvious and easy to fix.) +use std::cell::RefCell; use std::hash::Hash; +use std::rc::Rc; use std::sync::Arc; use std::{fmt, iter, mem}; @@ -1294,74 +1296,97 @@ impl DesugaringKind { #[derive(Default)] pub struct HygieneEncodeContext { /// All `SyntaxContexts` for which we have written `SyntaxContextData` into crate metadata. - /// This is `None` after we finish encoding `SyntaxContexts`, to ensure - /// that we don't accidentally try to encode any more `SyntaxContexts` - serialized_ctxts: Lock>, + serialized_ctxts: FxHashSet, /// The `SyntaxContexts` that we have serialized (e.g. as a result of encoding `Spans`) /// in the most recent 'round' of serializing. Serializing `SyntaxContextData` /// may cause us to serialize more `SyntaxContext`s, so serialize in a loop /// until we reach a fixed point. - latest_ctxts: Lock>, + latest_ctxts: FxHashSet, - serialized_expns: Lock>, - - latest_expns: Lock>, + serialized_expns: FxHashSet, + latest_expns: FxHashSet, } impl HygieneEncodeContext { /// Record the fact that we need to serialize the corresponding `ExpnData`. - pub fn schedule_expn_data_for_encoding(&self, expn: ExpnId) { - if !self.serialized_expns.lock().contains(&expn) { - self.latest_expns.lock().insert(expn); - } + #[inline] + pub fn schedule_expn_data_for_encoding(&mut self, expn: ExpnId) { + self.latest_expns.insert(expn); } pub fn encode( - &self, + h_ctxt: &RefCell, encoder: &mut T, mut encode_ctxt: impl FnMut(&mut T, u32, &SyntaxContextKey), - mut encode_expn: impl FnMut(&mut T, ExpnId, &ExpnData, ExpnHash), + mut encode_expn: impl FnMut(&mut T, ExpnId, Option<&ExpnData>, ExpnHash), ) { // When we serialize a `SyntaxContextData`, we may end up serializing // a `SyntaxContext` that we haven't seen before - while !self.latest_ctxts.lock().is_empty() || !self.latest_expns.lock().is_empty() { + + // Reuse the capacity between the loop iterations below. + let mut all_ctxt_data = vec![]; + let mut all_expn_data = vec![]; + + while { + let h_ctxt = h_ctxt.borrow(); + !h_ctxt.latest_ctxts.is_empty() || !h_ctxt.latest_expns.is_empty() + } { debug!( "encode_hygiene: Serializing a round of {:?} SyntaxContextData: {:?}", - self.latest_ctxts.lock().len(), - self.latest_ctxts + h_ctxt.borrow().latest_ctxts.len(), + h_ctxt.borrow().latest_ctxts ); + let mut mut_hctxt = h_ctxt.borrow_mut(); + // Consume the current round of syntax contexts. - // Drop the lock() temporary early. - // It's fine to iterate over a HashMap, because the serialization of the table + // It's fine to iterate over a HashSet, because the serialization of the table // that we insert data into doesn't depend on insertion order. #[allow(rustc::potential_query_instability)] - let latest_ctxts = { mem::take(&mut *self.latest_ctxts.lock()) }.into_iter(); - let all_ctxt_data: Vec<_> = HygieneData::with(|data| { - latest_ctxts - .map(|ctxt| (ctxt, data.syntax_context_data[ctxt.0 as usize].key())) - .collect() - }); - for (ctxt, ctxt_key) in all_ctxt_data { - if self.serialized_ctxts.lock().insert(ctxt) { - encode_ctxt(encoder, ctxt.0, &ctxt_key); + let latest_ctxts = { mem::take(&mut mut_hctxt.latest_ctxts) }.into_iter(); + + HygieneData::with(|data| { + for ctxt in latest_ctxts { + if !mut_hctxt.serialized_ctxts.insert(ctxt) { + continue; + } + + all_ctxt_data.push((ctxt.0, data.syntax_context_data[ctxt.0 as usize].key())); } + }); + + drop(mut_hctxt); + + for (idx, ctxt_key) in all_ctxt_data.drain(..) { + encode_ctxt(encoder, idx, &ctxt_key); } + let mut mut_hctxt = h_ctxt.borrow_mut(); + // Same as above, but for expansions instead of syntax contexts. #[allow(rustc::potential_query_instability)] - let latest_expns = { mem::take(&mut *self.latest_expns.lock()) }.into_iter(); - let all_expn_data: Vec<_> = HygieneData::with(|data| { - latest_expns - .map(|expn| (expn, data.expn_data(expn).clone(), data.expn_hash(expn))) - .collect() - }); - for (expn, expn_data, expn_hash) in all_expn_data { - if self.serialized_expns.lock().insert(expn) { - encode_expn(encoder, expn, &expn_data, expn_hash); + let latest_expns = { mem::take(&mut mut_hctxt.latest_expns) }.into_iter(); + HygieneData::with(|data| { + for expn in latest_expns { + if !mut_hctxt.serialized_expns.insert(expn) { + continue; + } + + // We need `data` only for local expansions, so don't `data` for non-local + // expansions. + // FIXME: completely remove this clone + let expn_data = expn.as_local().map(|id| data.local_expn_data(id).clone()); + all_expn_data.push((expn, expn_data, data.expn_hash(expn))); } + }); + + drop(mut_hctxt); + + for (expn, expn_data, expn_hash) in all_expn_data.drain(..) { + encode_expn(encoder, expn, expn_data.as_ref(), expn_hash); } } + debug!("encode_hygiene: Done serializing SyntaxContextData"); } } @@ -1484,14 +1509,13 @@ impl Decodable for LocalExpnId { } } +#[inline] pub fn raw_encode_syntax_context( ctxt: SyntaxContext, - context: &HygieneEncodeContext, + context: Rc>, e: &mut impl Encoder, ) { - if !context.serialized_ctxts.lock().contains(&ctxt) { - context.latest_ctxts.lock().insert(ctxt); - } + context.borrow_mut().latest_ctxts.insert(ctxt); ctxt.0.encode(e); } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 17ffb52f4b333..71f16294efb41 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1253,6 +1253,7 @@ symbols! { macro_reexport, macro_use, macro_vis_matcher, + macroless_const_item_generic_const_args, macroless_generic_const_args, macros_in_extern, main, diff --git a/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs index 8f2746c461661..670cb5b5d10e6 100644 --- a/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs @@ -25,7 +25,7 @@ pub(crate) fn target() -> Target { metadata: TargetMetadata { description: Some("32-bit MSVC (Windows 10+)".into()), tier: Some(1), - host_tools: Some(true), + host_tools: Some(false), std: Some(true), }, pointer_width: 32, diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index 3e7b3d2ae2daa..406349b621958 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -130,7 +130,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let ocx = ObligationCtxt::new(self); let normalized_fn_sig = ocx.normalize(&ObligationCause::dummy(), param_env, fn_sig); if ocx.evaluate_obligations_error_on_ambiguity().no_errors() { - let normalized_fn_sig = self.resolve_vars_if_possible(normalized_fn_sig); + let normalized_fn_sig = self.deeply_resolve_ignoring_regions(normalized_fn_sig); if !normalized_fn_sig.has_infer() { return normalized_fn_sig; } @@ -158,7 +158,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { where M: FnOnce(String) -> Diag<'a>, { - let actual_ty = self.resolve_vars_if_possible(actual_ty); + let actual_ty = self.deeply_resolve_ignoring_regions(actual_ty); debug!("type_error_struct_with_diag({:?}, {:?})", sp, actual_ty); let mut err = mk_diag(self.ty_to_string(actual_ty)); @@ -336,7 +336,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { span: Some(span), root_ty, } => { - let expected_ty = self.resolve_vars_if_possible(root_ty); + let expected_ty = self.deeply_resolve_ignoring_regions(root_ty); if !matches!( expected_ty.kind(), ty::Infer(ty::InferTy::TyVar(_) | ty::InferTy::FreshTy(_)) @@ -466,7 +466,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } _ => { // `prior_arm_ty` can be `!`, `expected` will have better info when present. - let t = self.resolve_vars_if_possible(match exp_found { + let t = self.deeply_resolve_ignoring_regions(match exp_found { Some(ty::error::ExpectedFound { expected, .. }) => expected, _ => prior_arm_ty, }); @@ -1576,7 +1576,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let (expected_found, exp_found, is_simple_error, values, param_env) = match values { None => (None, Mismatch::Fixed("type"), false, None, None), Some(ty::ParamEnvAnd { param_env, value: values }) => { - let values = self.resolve_vars_if_possible(values); + let values = self.deeply_resolve_ignoring_regions(values); let (is_simple_error, exp_found) = match values { ValuePairs::Terms(ExpectedFound { expected, found }) => { match (expected.kind(), found.kind()) { @@ -1988,7 +1988,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ) -> Vec { let mut suggestions = Vec::new(); let span = trace.cause.span; - let values = self.resolve_vars_if_possible(trace.values); + let values = self.deeply_resolve_ignoring_regions(trace.values); if let Some((expected, found)) = values.ty() { match (expected.kind(), found.kind()) { (ty::Tuple(_), ty::Tuple(_)) => {} @@ -2344,7 +2344,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } ValuePairs::PolySigs(exp_found) => { - let exp_found = self.resolve_vars_if_possible(exp_found); + let exp_found = self.deeply_resolve_ignoring_regions(exp_found); if exp_found.references_error() { return None; } @@ -2369,7 +2369,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { exp_found: ty::error::ExpectedFound>, long_ty_path: &mut Option, ) -> Option<(DiagStyledString, DiagStyledString)> { - let exp_found = self.resolve_vars_if_possible(exp_found); + let exp_found = self.deeply_resolve_ignoring_regions(exp_found); if exp_found.references_error() { return None; } @@ -2441,7 +2441,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { &self, exp_found: ty::error::ExpectedFound, ) -> Option<(DiagStyledString, DiagStyledString)> { - let exp_found = self.resolve_vars_if_possible(exp_found); + let exp_found = self.deeply_resolve_ignoring_regions(exp_found); if exp_found.references_error() { return None; } @@ -2467,7 +2467,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { /// FloatVar inference type are compatible with themselves or their concrete types (Int and /// Float types, respectively). When comparing two ADTs, these rules apply recursively. pub fn same_type_modulo_infer>>(&self, a: T, b: T) -> bool { - let (a, b) = self.resolve_vars_if_possible((a, b)); + let (a, b) = self.deeply_resolve_ignoring_regions((a, b)); SameTypeModuloInfer(self).relate(a, b).is_ok() } } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs index 38c6be6069e9a..10694c7990ec1 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs @@ -88,7 +88,7 @@ impl InferenceDiagnosticsData { "" } else if self.name == "_" { let displayed_ty = infcx - .resolve_vars_if_possible(in_type) + .deeply_resolve_ignoring_regions(in_type) .fold_with(&mut ClosureEraser { infcx, depth: 0 }); if displayed_ty.is_ty_or_numeric_infer() { "" @@ -308,7 +308,7 @@ fn ty_to_string<'tcx>( called_method_def_id: Option, ) -> String { let mut p = fmt_printer(infcx, Namespace::TypeNS); - let ty = infcx.resolve_vars_if_possible(ty); + let ty = infcx.deeply_resolve_ignoring_regions(ty); // We use `fn` ptr syntax for closures, but this only works when the closure does not capture // anything. We also remove all type parameters that are fully known to the type system. let ty = ty.fold_with(&mut ClosureEraser { infcx, depth: 0 }); @@ -507,7 +507,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { should_label_span: bool, ty: Option>, ) -> Diag<'a> { - let term = self.resolve_vars_if_possible(term); + let term = self.deeply_resolve_ignoring_regions(term); let arg_data = self .extract_inference_diagnostics_data(term, ty::print::RegionHighlightMode::default()); @@ -1023,12 +1023,12 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { fn node_args_opt(&self, hir_id: HirId) -> Option> { let args = self.typeck_results.node_args_opt(hir_id); - self.tecx.resolve_vars_if_possible(args) + self.tecx.deeply_resolve_ignoring_regions(args) } fn opt_node_type(&self, hir_id: HirId) -> Option> { let ty = self.typeck_results.node_type_opt(hir_id); - self.tecx.resolve_vars_if_possible(ty) + self.tecx.deeply_resolve_ignoring_regions(ty) } // Check whether this generic argument is the inference variable we @@ -1416,7 +1416,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> { .iter() .position(|&arg| self.generic_arg_contains_target(arg)) { - let args = self.tecx.resolve_vars_if_possible(args); + let args = self.tecx.deeply_resolve_ignoring_regions(args); let generic_args = &generics.own_args_no_defaults(tcx, args)[generics.own_counts().lifetimes..]; let span = match expr.kind { @@ -1497,7 +1497,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> { { let successor = method_args.get(0).map_or_else(|| (")", span.hi()), |arg| (", ", arg.span.lo())); - let args = self.tecx.resolve_vars_if_possible(args); + let args = self.tecx.deeply_resolve_ignoring_regions(args); self.update_infer_source(InferSource { span: path.ident.span, kind: InferSourceKind::FullyQualifiedMethodCall { diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs index 7f07fab6e8474..6b97651d5f968 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs @@ -271,16 +271,12 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { (false, None, None, Some(span), String::new()) }; - let expected_trait_ref = self.cx.resolve_vars_if_possible(ty::TraitRef::new_from_args( - self.cx.tcx, - trait_def_id, - expected_args, - )); - let actual_trait_ref = self.cx.resolve_vars_if_possible(ty::TraitRef::new_from_args( - self.cx.tcx, - trait_def_id, - actual_args, - )); + let expected_trait_ref = self.cx.deeply_resolve_ignoring_regions( + ty::TraitRef::new_from_args(self.cx.tcx, trait_def_id, expected_args), + ); + let actual_trait_ref = self.cx.deeply_resolve_ignoring_regions( + ty::TraitRef::new_from_args(self.cx.tcx, trait_def_id, actual_args), + ); // Search the expected and actual trait references to see (a) // whether the sub/sup placeholders appear in them (sometimes @@ -400,7 +396,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { // the confusing lifetime-generality error into an actionable hint, e.g.: // |buf| → |buf: &mut [u8]| if self.tcx().is_fn_trait(trait_def_id) { - let actual_self_ty = self.cx.resolve_vars_if_possible( + let actual_self_ty = self.cx.deeply_resolve_ignoring_regions( ty::TraitRef::new_from_args(self.cx.tcx, trait_def_id, actual_args).self_ty(), ); if let ty::Closure(closure_def_id, _) = *actual_self_ty.kind() diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs index 45ae86b39f35e..b6df361546512 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs @@ -990,7 +990,7 @@ fn foo(&self) -> Self::T { String::new() } msg: impl Fn() -> String, is_bound_surely_present: bool, ) -> bool { - // FIXME: we would want to call `resolve_vars_if_possible` on `ty` before suggesting. + // FIXME: we would want to call `deeply_resolve_ignoring_regions` on `ty` before suggesting. let trait_bounds = bounds.iter().filter_map(|bound| match bound { hir::GenericBound::Trait(ptr) if ptr.modifiers == hir::TraitBoundModifiers::NONE => { diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index 73b98b8eda1a6..37076b0b655f2 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -430,7 +430,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ); self.dcx().create_err(FulfillReqLifetime { span, - ty: self.resolve_vars_if_possible(ty), + ty: self.deeply_resolve_ignoring_regions(ty), note, }) } @@ -495,7 +495,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ); self.dcx().create_err(RefLongerThanData { span, - ty: self.resolve_vars_if_possible(ty), + ty: self.deeply_resolve_ignoring_regions(ty), notes: pointer_valid.into_iter().chain(data_valid).collect(), }) } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs index db852701051cf..b5235fa443575 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs @@ -48,8 +48,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { second_span: Span, ) -> Option { let remove_semicolon = [ - (first_id, self.resolve_vars_if_possible(second_ty)), - (second_id, self.resolve_vars_if_possible(first_ty)), + (first_id, self.deeply_resolve_ignoring_regions(second_ty)), + (second_id, self.deeply_resolve_ignoring_regions(first_ty)), ] .into_iter() .find_map(|(id, ty)| { @@ -926,7 +926,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { .as_ref() .and_then(|typeck_results| typeck_results.node_type_opt(*hir_id)) { - let pat_ty = self.resolve_vars_if_possible(pat_ty); + let pat_ty = self.deeply_resolve_ignoring_regions(pat_ty); if self.same_type_modulo_infer(pat_ty, expected_ty) && !(pat_ty, expected_ty).references_error() && shadowed.insert(ident.name) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs index 2b7a20c90c87b..a44d53cdfdd05 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs @@ -213,7 +213,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // ambiguous impls. The latter *ought* to be a // coherence violation, so we don't report it here. - let predicate = self.resolve_vars_if_possible(obligation.predicate); + let predicate = self.deeply_resolve_ignoring_regions(obligation.predicate); let span = obligation.cause.span; let mut long_ty_path = None; @@ -711,7 +711,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let mut mentioned = vec![predicate]; let mut mentioned_strs: Vec = vec![]; for &error in related { - let related_pred = self.resolve_vars_if_possible(error.obligation.predicate); + let related_pred = self.deeply_resolve_ignoring_regions(error.obligation.predicate); if mentioned.contains(&related_pred) { continue; } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 5b029d6fad5d4..7ee4481d12431 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -111,8 +111,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let bound_predicate = obligation.predicate.kind(); match bound_predicate.skip_binder() { ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => { - let leaf_trait_predicate = - self.resolve_vars_if_possible(bound_predicate.rebind(trait_predicate)); + let leaf_trait_predicate = self.deeply_resolve_ignoring_regions( + bound_predicate.rebind(trait_predicate), + ); // Let's use the root obligation as the main message, when we care about the // most general case ("X doesn't implement Pattern<'_>") over the case that @@ -153,7 +154,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { && !self.tcx.is_lang_item(root_pred.def_id(), LangItem::Unsize) { ( - self.resolve_vars_if_possible( + self.deeply_resolve_ignoring_regions( root_obligation.predicate.kind().rebind(root_pred), ), root_obligation, @@ -710,7 +711,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(ty)) => { - let ty = self.resolve_vars_if_possible(ty); + let ty = self.deeply_resolve_ignoring_regions(ty); if self.next_trait_solver() { if let Err(guar) = ty.error_reported() { return guar; @@ -1202,7 +1203,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let noted_missing_impl = self.note_missing_impl_for_question_mark(err, self_ty, found_ty, trait_pred); - let mut prev_ty = self.resolve_vars_if_possible( + let mut prev_ty = self.deeply_resolve_ignoring_regions( typeck.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(self.tcx)), ); @@ -1234,7 +1235,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { expr = rcvr_expr; chain.push((span, prev_ty)); - let next_ty = self.resolve_vars_if_possible( + let next_ty = self.deeply_resolve_ignoring_regions( typeck.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(self.tcx)), ); @@ -1277,7 +1278,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // The last statement is of a type that can be converted to the return error type && let [.., stmt] = block.stmts && let hir::StmtKind::Semi(expr) = stmt.kind - && let expr_ty = self.resolve_vars_if_possible( + && let expr_ty = self.deeply_resolve_ignoring_regions( typeck.expr_ty_adjusted_opt(expr) .unwrap_or(Ty::new_misc_error(self.tcx)), ) @@ -1322,7 +1323,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // `expr` is now the "root" expression of the method call chain, which can be any // expression kind, like a method call or a path. If this expression is `Result` as // well, then we also point at it. - prev_ty = self.resolve_vars_if_possible( + prev_ty = self.deeply_resolve_ignoring_regions( typeck.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(self.tcx)), ); chain.push((expr.span, prev_ty)); @@ -1669,7 +1670,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { obligation: &PredicateObligation<'tcx>, error: &MismatchedProjectionTypes<'tcx>, ) -> ErrorGuaranteed { - let predicate = self.resolve_vars_if_possible(obligation.predicate); + let predicate = self.deeply_resolve_ignoring_regions(obligation.predicate); if let Err(e) = predicate.error_reported() { return e; @@ -1710,7 +1711,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ( Some(( data.projection_term, - self.resolve_vars_if_possible(normalized_term), + self.deeply_resolve_ignoring_regions(normalized_term), data.term, )), new_err, @@ -1737,8 +1738,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ( with_forced_trimmed_paths!(format!( "type mismatch resolving `{}`", - self.tcx - .short_string(self.resolve_vars_if_possible(predicate), &mut file), + self.tcx.short_string( + self.deeply_resolve_ignoring_regions(predicate), + &mut file + ), )), obligation.cause.span, None, @@ -1872,7 +1875,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { with_forced_trimmed_paths!(Cow::from(format!( "type mismatch resolving `{}`", self.tcx.short_string( - self.resolve_vars_if_possible(predicate), + self.deeply_resolve_ignoring_regions(predicate), diag.long_ty_path() ), ))), @@ -2280,7 +2283,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { return false; } - let impl_trait_ref = self.resolve_vars_if_possible(impl_trait_ref); + let impl_trait_ref = self.deeply_resolve_ignoring_regions(impl_trait_ref); if impl_trait_ref.references_error() { return false; } @@ -2362,7 +2365,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { err.highlighted_span_help(self.tcx.def_span(single.impl_def_id), msg); if let [TypeError::Sorts(exp_found)] = &terrs[..] { - let exp_found = self.resolve_vars_if_possible(*exp_found); + let exp_found = self.deeply_resolve_ignoring_regions(*exp_found); let expected = self.tcx.short_string(exp_found.expected, err.long_ty_path()); let found = self.tcx.short_string(exp_found.found, err.long_ty_path()); @@ -2783,7 +2786,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ) -> Option<(Ty<'tcx>, Option)> { match code { ObligationCauseCode::BuiltinDerived(data) => { - let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred); + let parent_trait_ref = self.deeply_resolve_ignoring_regions(data.parent_trait_pred); match self.get_parent_trait_ref(&data.parent_code) { Some(t) => Some(t), None => { @@ -3117,7 +3120,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { cause_code: &ObligationCauseCode<'tcx>, ) -> bool { if let ObligationCauseCode::BuiltinDerived(data) = cause_code { - let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred); + let parent_trait_ref = self.deeply_resolve_ignoring_regions(data.parent_trait_pred); let self_ty = parent_trait_ref.skip_binder().self_ty(); if obligated_types.iter().any(|ot| ot == &self_ty) { return true; @@ -3646,8 +3649,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { found_trait_ref: ty::TraitRef<'tcx>, expected_trait_ref: ty::TraitRef<'tcx>, ) -> Result, ErrorGuaranteed> { - let found_trait_ref = self.resolve_vars_if_possible(found_trait_ref); - let expected_trait_ref = self.resolve_vars_if_possible(expected_trait_ref); + let found_trait_ref = self.deeply_resolve_ignoring_regions(found_trait_ref); + let expected_trait_ref = self.deeply_resolve_ignoring_regions(expected_trait_ref); expected_trait_ref.self_ty().error_reported()?; let found_trait_ty = found_trait_ref.self_ty(); @@ -3962,7 +3965,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { self.tcx .fn_trait_kind_from_def_id(trait_def_id) .expect("expected to map DefId to ClosureKind"), - ty.rebind(self.resolve_vars_if_possible(var)), + ty.rebind(self.deeply_resolve_ignoring_regions(var)), )); } } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs index ab6aa9c58d9c2..b0a513f692c38 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs @@ -280,7 +280,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // roots, like `need_type_info` does when looking for the annotation source. let ambiguity_infer_var = |error: &FulfillmentError<'tcx>| match error.code { FulfillmentErrorCode::Ambiguity { overflow: None } => self - .ambiguity_term(self.resolve_vars_if_possible(error.obligation.predicate)) + .ambiguity_term(self.deeply_resolve_ignoring_regions(error.obligation.predicate)) .and_then(|term| { ty::GenericArg::from(term) .walk() diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs index 30a18a928e842..e8765e3b0ad27 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs @@ -77,7 +77,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let mut err = match cause { OverflowCause::DeeplyNormalize(alias_term) => { - let alias_term = self.resolve_vars_if_possible(alias_term); + let alias_term = self.deeply_resolve_ignoring_regions(alias_term); let kind = alias_term.kind.descr(); let alias_str = with_short_path(self.tcx, alias_term); struct_span_code_err!( @@ -88,7 +88,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ) } OverflowCause::TraitSolver(predicate) => { - let predicate = self.resolve_vars_if_possible(predicate); + let predicate = self.deeply_resolve_ignoring_regions(predicate); match predicate.kind().skip_binder() { ty::PredicateKind::Subtype(ty::SubtypePredicate { a, b, a_is_expected: _ }) | ty::PredicateKind::Coerce(ty::CoercePredicate { a, b }) => { @@ -143,7 +143,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { T: Upcast, ty::Predicate<'tcx>> + Clone, { let predicate = obligation.predicate.clone().upcast(self.tcx); - let predicate = self.resolve_vars_if_possible(predicate); + let predicate = self.deeply_resolve_ignoring_regions(predicate); self.report_overflow_error( OverflowCause::TraitSolver(predicate), obligation.cause.span, @@ -168,7 +168,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { /// we do not suggest increasing the overflow limit, which is not /// going to help). pub fn report_overflow_obligation_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! { - let cycle = self.resolve_vars_if_possible(cycle.to_owned()); + let cycle = self.deeply_resolve_ignoring_regions(cycle.to_owned()); assert!(!cycle.is_empty()); debug!(?cycle, "report_overflow_error_cycle"); @@ -186,7 +186,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { obligation: PredicateObligation<'tcx>, suggest_increasing_limit: bool, ) -> ErrorGuaranteed { - let obligation = self.resolve_vars_if_possible(obligation); + let obligation = self.deeply_resolve_ignoring_regions(obligation); let mut err = self.build_overflow_error( OverflowCause::TraitSolver(obligation.predicate), obligation.cause.span, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 95bb2fd7e40c5..0b178f86249a9 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -82,7 +82,7 @@ impl<'a, 'tcx> CoroutineData<'a, 'tcx> { infer_context.tcx.upvars_mentioned(coroutine_did).and_then(|upvars| { upvars.iter().find_map(|(upvar_id, upvar)| { let upvar_ty = self.0.node_type(*upvar_id); - let upvar_ty = infer_context.resolve_vars_if_possible(upvar_ty); + let upvar_ty = infer_context.deeply_resolve_ignoring_regions(upvar_ty); ty_matches(ty::Binder::dummy(upvar_ty)) .then(|| CoroutineInteriorOrUpvar::Upvar(upvar.span)) }) @@ -328,7 +328,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let Some(base_ty) = typeck_results.expr_ty_opt(base_expr) else { return; }; - let base_ty = self.resolve_vars_if_possible(base_ty); + let base_ty = self.deeply_resolve_ignoring_regions(base_ty); if base_ty.references_error() { return; } @@ -1357,7 +1357,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { err.span_label(block.span, "this block is missing a tail expression"); return; }; - let ty = self.resolve_numeric_literals_with_default(self.resolve_vars_if_possible(ty)); + let ty = + self.resolve_numeric_literals_with_default(self.deeply_resolve_ignoring_regions(ty)); let trait_pred_and_self = trait_pred.map_bound(|trait_pred| (trait_pred, ty)); let new_obligation = @@ -1382,7 +1383,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { err: &mut Diag<'_>, trait_pred: ty::PolyTraitClause<'tcx>, ) -> bool { - let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty()); + let self_ty = self.deeply_resolve_ignoring_regions(trait_pred.self_ty()); self.enter_forall(self_ty, |ty: Ty<'_>| { let Some(generics) = self.tcx.hir_get_generics(obligation.cause.body_def_id) else { return false; @@ -2498,7 +2499,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // Do not suggest removal of borrow from type arguments. return; } - let trait_pred = self.resolve_vars_if_possible(trait_pred); + let trait_pred = self.deeply_resolve_ignoring_regions(trait_pred); if trait_pred.has_non_region_infer() { // Do not ICE while trying to find if a reborrow would succeed on a trait with // unresolved bindings. @@ -2604,7 +2605,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // Only suggest this if the expression behind the semicolon implements the predicate && let Some(typeck_results) = &self.typeck_results && let Some(ty) = - typeck_results.expr_ty_opt(expr).map(|ty| self.resolve_vars_if_possible(ty)) + typeck_results.expr_ty_opt(expr).map(|ty| self.deeply_resolve_ignoring_regions(ty)) && self.predicate_may_hold(&self.mk_trait_obligation_with_new_self_ty( obligation.param_env, trait_pred.map_bound(|trait_pred| (trait_pred, ty)) )) @@ -2716,7 +2717,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { hir::ExprKind::Closure(closure) => closure.def_id, _ => match typeck_results .expr_ty_adjusted_opt(arg) - .map(|ty| *self.resolve_vars_if_possible(ty).peel_refs().kind()) + .map(|ty| *self.deeply_resolve_ignoring_regions(ty).peel_refs().kind()) { Some(ty::Closure(def_id, _)) => def_id.as_local()?, _ => return None, @@ -3795,10 +3796,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } let capture_ty = - self.tcx.erase_and_anonymize_regions(self.resolve_vars_if_possible(capture_ty)); + self.tcx.erase_and_anonymize_regions(self.deeply_resolve_ignoring_regions(capture_ty)); let Some(capture) = captures.iter().zip(upvar_tys).find_map(|(&capture, upvar_ty)| { - let upvar_ty = - self.tcx.erase_and_anonymize_regions(self.resolve_vars_if_possible(upvar_ty)); + let upvar_ty = self + .tcx + .erase_and_anonymize_regions(self.deeply_resolve_ignoring_regions(upvar_ty)); (upvar_ty == capture_ty).then_some(capture) }) else { return false; @@ -4133,10 +4135,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } ObligationCauseCode::Coercion { source, target } => { - let source = - tcx.short_string(self.resolve_vars_if_possible(source), err.long_ty_path()); - let target = - tcx.short_string(self.resolve_vars_if_possible(target), err.long_ty_path()); + let source = tcx + .short_string(self.deeply_resolve_ignoring_regions(source), err.long_ty_path()); + let target = tcx + .short_string(self.deeply_resolve_ignoring_regions(target), err.long_ty_path()); err.note(with_forced_trimmed_paths!(format!( "required for the cast from `{source}` to `{target}`", ))); @@ -4408,7 +4410,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { err.note("shared static variables must have a type that implements `Sync`"); } ObligationCauseCode::BuiltinDerived(ref data) => { - let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred); + let parent_trait_ref = self.deeply_resolve_ignoring_regions(data.parent_trait_pred); let ty = parent_trait_ref.skip_binder().self_ty(); if parent_trait_ref.references_error() { // NOTE(eddyb) this was `.cancel()`, but `err` @@ -4422,7 +4424,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let is_upvar_tys_infer_tuple = if !matches!(ty.kind(), ty::Tuple(..)) { false } else if let ObligationCauseCode::BuiltinDerived(data) = &*data.parent_code { - let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred); + let parent_trait_ref = + self.deeply_resolve_ignoring_regions(data.parent_trait_pred); let nested_ty = parent_trait_ref.skip_binder().self_ty(); matches!(nested_ty.kind(), ty::Coroutine(..)) || matches!(nested_ty.kind(), ty::Closure(..)) @@ -4559,7 +4562,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } ObligationCauseCode::ImplDerived(ref data) => { let mut parent_trait_pred = - self.resolve_vars_if_possible(data.derived.parent_trait_pred); + self.deeply_resolve_ignoring_regions(data.derived.parent_trait_pred); let parent_def_id = parent_trait_pred.def_id(); if tcx.is_diagnostic_item(sym::FromResidual, parent_def_id) && !tcx.features().enabled(sym::try_trait_v2) @@ -4571,7 +4574,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } if tcx.is_diagnostic_item(sym::PinDerefMutHelper, parent_def_id) { let parent_predicate = - self.resolve_vars_if_possible(data.derived.parent_trait_pred); + self.deeply_resolve_ignoring_regions(data.derived.parent_trait_pred); // Skip PinDerefMutHelper in suggestions, but still show downstream suggestions. @@ -4697,7 +4700,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // the type `X`", like we would otherwise do in test `supertrait-auto-trait.rs`. while let ObligationCauseCode::BuiltinDerived(derived) = &*data.parent_code { let child_trait_ref = - self.resolve_vars_if_possible(derived.parent_trait_pred); + self.deeply_resolve_ignoring_regions(derived.parent_trait_pred); let child_def_id = child_trait_ref.def_id(); if seen_requirements.insert(child_def_id) { break; @@ -4710,7 +4713,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { while let ObligationCauseCode::ImplDerived(child) = &*data.parent_code { // Skip redundant recursive obligation notes. See `ui/issue-20413.rs`. let child_trait_pred = - self.resolve_vars_if_possible(child.derived.parent_trait_pred); + self.deeply_resolve_ignoring_regions(child.derived.parent_trait_pred); let child_def_id = child_trait_pred.def_id(); if seen_requirements.insert(child_def_id) { break; @@ -4750,7 +4753,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } ObligationCauseCode::ImplDerivedHost(ref data) => { let self_ty = tcx.short_string( - self.resolve_vars_if_possible(data.derived.parent_host_clause.self_ty()), + self.deeply_resolve_ignoring_regions(data.derived.parent_host_clause.self_ty()), err.long_ty_path(), ); let trait_path = tcx.short_string( @@ -4804,7 +4807,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ); } ObligationCauseCode::WellFormedDerived(ref data) => { - let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred); + let parent_trait_ref = self.deeply_resolve_ignoring_regions(data.parent_trait_pred); let parent_predicate = parent_trait_ref; *closure_capture_ty = Some(parent_trait_ref.skip_binder().self_ty()); @@ -4979,7 +4982,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ) { let future_trait = self.tcx.require_lang_item(LangItem::Future, span); - let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty()); + let self_ty = self.deeply_resolve_ignoring_regions(trait_pred.self_ty()); let impls_future = self.type_implements_trait( future_trait, [self.tcx.instantiate_bound_regions_with_erased(self_ty)], @@ -5005,7 +5008,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { .normalize(Unnormalized::new_wip(projection_ty)); debug!( - normalized_projection_type = ?self.resolve_vars_if_possible(projection_ty) + normalized_projection_type = ?self.deeply_resolve_ignoring_regions(projection_ty) ); let try_obligation = self.mk_trait_obligation_with_new_self_ty( obligation.param_env, @@ -5678,7 +5681,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let mut print_root_expr = true; let mut assocs = vec![]; let mut expr = expr; - let mut prev_ty = self.resolve_vars_if_possible( + let mut prev_ty = self.deeply_resolve_ignoring_regions( typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(tcx)), ); while let hir::ExprKind::MethodCall(path_segment, rcvr_expr, args, span) = expr.kind { @@ -5688,7 +5691,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { expr = rcvr_expr; let assocs_in_this_method = self.probe_assoc_types_at_expr(&type_diffs, span, prev_ty, expr.hir_id, param_env); - prev_ty = self.resolve_vars_if_possible( + prev_ty = self.deeply_resolve_ignoring_regions( typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(tcx)), ); self.look_for_iterator_item_mistakes( @@ -5717,7 +5720,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } if let hir::Node::Param(param) = parent { // ...and it is an fn argument. - let prev_ty = self.resolve_vars_if_possible( + let prev_ty = self.deeply_resolve_ignoring_regions( typeck_results .node_type_opt(param.hir_id) .unwrap_or(Ty::new_misc_error(tcx)), @@ -5882,7 +5885,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { projection, )); if ocx.try_evaluate_obligations().no_errors() - && let ty = self.resolve_vars_if_possible(ty) + && let ty = self.deeply_resolve_ignoring_regions(ty) && !ty.is_ty_var() { assocs_in_this_method.push(Some((span, (def_id, ty)))); @@ -5971,7 +5974,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // Resolve what each bound associated type actually is for the returned expression, // and keep only the ones that diverged from the signature. - let expr_ty = self.resolve_vars_if_possible( + let expr_ty = self.deeply_resolve_ignoring_regions( typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(tcx)), ); let assocs = self.probe_assoc_types_at_expr( @@ -6130,7 +6133,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let hir::ExprKind::MethodCall(segment, rcvr, args, ..) = call.kind else { return }; let Some(typeck) = &self.typeck_results else { return }; let Some(rcvr_ty) = typeck.expr_ty_adjusted_opt(rcvr) else { return }; - let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty); + let rcvr_ty = self.deeply_resolve_ignoring_regions(rcvr_ty); let autoderef = (self.autoderef_steps)(rcvr_ty); for (ty, def_id) in autoderef.iter().filter_map(|(ty, obligations)| { if let ty::Adt(def, _) = ty.kind() diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index f0fb44523d651..802393a22b7e5 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -31,13 +31,13 @@ impl<'tcx> InferCtxt<'tcx> { } fn type_is_copy_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool { - let ty = self.resolve_vars_if_possible(ty); + let ty = self.deeply_resolve_ignoring_regions(ty); let copy_def_id = self.tcx.require_lang_item(LangItem::Copy, DUMMY_SP); traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, copy_def_id) } fn type_is_clone_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool { - let ty = self.resolve_vars_if_possible(ty); + let ty = self.deeply_resolve_ignoring_regions(ty); let clone_def_id = self.tcx.require_lang_item(LangItem::Clone, DUMMY_SP); traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, clone_def_id) } @@ -47,7 +47,7 @@ impl<'tcx> InferCtxt<'tcx> { param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>, ) -> bool { - let ty = self.resolve_vars_if_possible(ty); + let ty = self.deeply_resolve_ignoring_regions(ty); let use_cloned_def_id = self.tcx.require_lang_item(LangItem::UseCloned, DUMMY_SP); traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, use_cloned_def_id) } diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index 818d8e1a4e0c3..c67a4bdd329b0 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -176,7 +176,7 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< } else if trait_pred.polarity() == ty::ClausePolarity::Positive { match self.0.tcx.as_lang_item(trait_pred.def_id()) { Some(LangItem::Sized) | Some(LangItem::MetaSized) => { - let predicate = self.resolve_vars_if_possible(goal.predicate); + let predicate = self.deeply_resolve_ignoring_regions(goal.predicate); if sizedness_fast_path(self.tcx, predicate, goal.param_env) { Outcome::TriviallyHolds } else { @@ -184,8 +184,9 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< } } Some(LangItem::Copy | LangItem::Clone) => { - let self_ty = - self.resolve_vars_if_possible(trait_pred.self_ty().skip_binder()); + let self_ty = self.deeply_resolve_ignoring_regions( + trait_pred.self_ty().skip_binder(), + ); // Unlike `Sized` traits, which always prefer the built-in impl, // `Copy`/`Clone` may be shadowed by a param-env candidate which // could force a lifetime error or guide inference. While that's @@ -227,7 +228,7 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< return Outcome::NoFastPath; } - let ty = self.resolve_vars_if_possible(outlives.0); + let ty = self.deeply_resolve_ignoring_regions(outlives.0); let mut infer_collector = CollectNonRegionInfer { infers: Default::default(), visited: Default::default(), @@ -459,7 +460,7 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< | TypingMode::Reflection | TypingMode::PostBorrowck { .. } => false, TypingMode::PostAnalysis | TypingMode::Codegen => { - let poly_trait_ref = self.resolve_vars_if_possible(goal_trait_ref); + let poly_trait_ref = self.deeply_resolve_ignoring_regions(goal_trait_ref); !poly_trait_ref.still_further_specializable() } TypingMode::ErasedNotCoherence(MayBeErased) => { @@ -514,7 +515,7 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< fn emit_next_solver_overflow_fcw(&self, goal: Goal<'tcx, ty::Predicate<'tcx>>, span: Span) { let tcx = self.tcx; - let goal = self.resolve_vars_if_possible(goal); + let goal = self.deeply_resolve_ignoring_regions(goal); let mut visitor = OverflowedGoalChain { span, predicates: vec![], diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs index 1c7d5b742e1ac..de37087ac09ef 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs @@ -141,7 +141,7 @@ pub(super) fn try_ambiguity_error_for_stalled<'tcx>( root_obligation.cause.span, format!( "did not expect successful goal when collecting ambiguity errors for `{:?}`", - infcx.resolve_vars_if_possible(root_obligation.predicate), + infcx.deeply_resolve_ignoring_regions(root_obligation.predicate), ), ); None @@ -150,7 +150,7 @@ pub(super) fn try_ambiguity_error_for_stalled<'tcx>( span_bug!( root_obligation.cause.span, "did not expect selection error when collecting ambiguity errors for `{:?}`", - infcx.resolve_vars_if_possible(root_obligation.predicate), + infcx.deeply_resolve_ignoring_regions(root_obligation.predicate), ) } } @@ -178,7 +178,7 @@ fn find_best_leaf_obligation<'tcx>( obligation: &PredicateObligation<'tcx>, consider_ambiguities: bool, ) -> PredicateObligation<'tcx> { - let obligation = infcx.resolve_vars_if_possible(obligation.clone()); + let obligation = infcx.deeply_resolve_ignoring_regions(obligation.clone()); // FIXME: we use a probe here as the `BestObligation` visitor does not // check whether it uses candidates which get shadowed by where-bounds. // diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index aaba2f86da598..8c8af70f4af46 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -14,7 +14,7 @@ use std::assert_matches; use rustc_infer::infer::InferCtxt; use rustc_macros::extension; use rustc_middle::traits::solve::{Certainty, Goal, GoalSource, NoSolution, QueryResult}; -use rustc_middle::ty::{RequiredDepth, TyCtxt, VisitorResult, eager_resolve_vars, try_visit}; +use rustc_middle::ty::{RequiredDepth, TyCtxt, VisitorResult, try_visit}; use rustc_middle::{bug, ty}; use rustc_next_trait_solver::canonical::instantiate_canonical_state; use rustc_next_trait_solver::solve::{MaybeCause, MaybeInfo, SolverDelegateEvalExt as _, inspect}; @@ -145,6 +145,8 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { fields(goal = ?self.goal.goal, steps = ?self.steps) )] pub fn instantiate_impl_args(&self, span: Span) -> ty::GenericArgsRef<'tcx> { + use rustc_middle::ty::InferCtxtLike; + let infcx = self.goal.infcx; let param_env = self.goal.goal.param_env; let mut orig_values = self.goal.orig_values.clone(); @@ -170,7 +172,10 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { self.final_state, ); - return eager_resolve_vars(&**infcx, impl_args); + // We *want* this folder to live in `rustc_type_ir`. Our best way to call into it is + // through `InferCtxtLike` and it is not defined as an inherent method on `InferCtxt`. + #[allow(rustc::usage_of_type_ir_traits)] + return infcx.deeply_resolve_via_unification_table(impl_args); } inspect::ProbeStep::AddGoal(..) => {} inspect::ProbeStep::MakeCanonicalResponse { .. } @@ -342,6 +347,8 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { root: inspect::GoalEvaluation>, source: GoalSource, ) -> Self { + use rustc_middle::ty::InferCtxtLike; + let infcx = <&SolverDelegate<'tcx>>::from(infcx); let prev_universe = infcx.universe(); @@ -361,7 +368,10 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { depth, orig_values, prev_universe, - goal: eager_resolve_vars(&**infcx, uncanonicalized_goal), + // We *want* this folder to live in `rustc_type_ir`. Our best way to call into it is + // through `InferCtxtLike` and it is not defined as an inherent method on `InferCtxt`. + #[allow(rustc::usage_of_type_ir_traits)] + goal: infcx.deeply_resolve_via_unification_table(uncanonicalized_goal), result, final_revision, source, diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs index bff35154ed10d..9430b6c4b3307 100644 --- a/compiler/rustc_trait_selection/src/solve/normalize.rs +++ b/compiler/rustc_trait_selection/src/solve/normalize.rs @@ -42,7 +42,7 @@ where { let infcx = at.infcx; let value = value.skip_normalization(); - let value = infcx.resolve_vars_if_possible(value); + let value = infcx.deeply_resolve_ignoring_regions(value); if !infcx.tcx.renormalize_rigid_aliases() && !value.has_non_rigid_aliases() { return Normalized { value, obligations: Default::default() }; @@ -59,7 +59,7 @@ where Ok(result) => result, Err(err) => return Err(err), }; - let normalized = infcx.resolve_vars_if_possible(infer_term); + let normalized = infcx.deeply_resolve_ignoring_regions(infer_term); let normalization_was_ambiguous = match result.certainty { Certainty::Yes => NormalizationWasAmbiguous::No, Certainty::Maybe { .. } => { diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 8667eb3af3da7..fadc64ed4af5c 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -334,9 +334,9 @@ impl<'tcx> AutoTraitFinder<'tcx> { continue; } - // Call `infcx.resolve_vars_if_possible` to see if we can + // Call `infcx.deeply_resolve_ignoring_regions` to see if we can // get rid of any inference variables. - let obligation = infcx.resolve_vars_if_possible(Obligation::new( + let obligation = infcx.deeply_resolve_ignoring_regions(Obligation::new( tcx, dummy_cause.clone(), new_env, @@ -658,7 +658,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { fresh_preds.insert(self.clean_pred(selcx.infcx, obligation.predicate)); // Resolve any inference variables that we can, to help selection succeed - let predicate = selcx.infcx.resolve_vars_if_possible(obligation.predicate); + let predicate = selcx.infcx.deeply_resolve_ignoring_regions(obligation.predicate); // We only add a predicate as a user-displayable bound if // it involves a generic parameter, and doesn't contain diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 24217aaf75fe7..5605325309275 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -333,7 +333,7 @@ fn overlap<'tcx>( .iter() .any(|c| c.0.involves_placeholders()); - let mut impl_header = infcx.resolve_vars_if_possible(impl1_header); + let mut impl_header = infcx.deeply_resolve_ignoring_regions(impl1_header); // Deeply normalize the impl header for diagnostics, ignoring any errors if this fails. if infcx.next_trait_solver() { @@ -451,7 +451,7 @@ fn impl_intersection_has_impossible_obligation<'a, 'cx, 'tcx>( .filter(|error| { matches!(error.code, FulfillmentErrorCode::Ambiguity { overflow: Some(true) }) }) - .map(|e| infcx.resolve_vars_if_possible(e.obligation.predicate)) + .map(|e| infcx.deeply_resolve_ignoring_regions(e.obligation.predicate)) .collect(), } } else { @@ -540,8 +540,9 @@ fn impl_intersection_has_negative_obligation( // Right above we plug inference variables with placeholders, // this gets us new impl1_header_args with the inference variables actually resolved // to those placeholders. - let impl1_header_args = infcx.resolve_vars_if_possible(impl1_header.impl_args); - // So there are no infer variables left now, except regions which aren't resolved by `resolve_vars_if_possible`. + let impl1_header_args = infcx.deeply_resolve_ignoring_regions(impl1_header.impl_args); + // So there are no infer variables left now, except regions which aren't resolved by + // `deeply_resolve_ignoring_regions`. assert!(!impl1_header_args.has_non_region_infer()); let param_env = ty::EarlyBinder::bind(tcx, tcx.param_env(impl1_def_id)) @@ -637,7 +638,7 @@ fn plug_infer_with_placeholders<'tcx>( .inner .borrow_mut() .unwrap_region_constraints() - .opportunistic_resolve_var(self.infcx.tcx, vid); + .shallow_resolve_region_var(self.infcx.tcx, vid); if r.is_var() { let Ok(InferOk { value: (), obligations }) = self.infcx.at(&ObligationCause::dummy(), ty::ParamEnv::empty()).eq( diff --git a/compiler/rustc_trait_selection/src/traits/effects.rs b/compiler/rustc_trait_selection/src/traits/effects.rs index 127a46f60b3d9..631d404d93845 100644 --- a/compiler/rustc_trait_selection/src/traits/effects.rs +++ b/compiler/rustc_trait_selection/src/traits/effects.rs @@ -33,7 +33,7 @@ pub fn evaluate_host_effect_obligation<'tcx>( ); } - let ref obligation = selcx.infcx.resolve_vars_if_possible(obligation.clone()); + let ref obligation = selcx.infcx.deeply_resolve_ignoring_regions(obligation.clone()); // Force ambiguity for infer self ty. if obligation.predicate.self_ty().is_ty_var() { diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index ddbb56affcff1..c51c5feafb4a2 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -145,7 +145,7 @@ where // this helps to reduce duplicate errors, as well as making // debug output much nicer to read and so on. debug_assert!(!obligation.param_env.has_non_region_infer()); - obligation.predicate = infcx.resolve_vars_if_possible(obligation.predicate); + obligation.predicate = infcx.deeply_resolve_ignoring_regions(obligation.predicate); debug!(?obligation, "register_predicate_obligation"); @@ -236,7 +236,7 @@ where } self.infcx - .resolve_vars_if_possible(pending_obligation.obligation.predicate) + .deeply_resolve_ignoring_regions(pending_obligation.obligation.predicate) .visit_with(&mut StalledOnCoroutines { stalled_coroutines: self.stalled_coroutines, cache: Default::default(), @@ -387,7 +387,8 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { debug!(?obligation, "pre-resolve"); if obligation.predicate.has_non_region_infer() { - obligation.predicate = self.selcx.infcx.resolve_vars_if_possible(obligation.predicate); + obligation.predicate = + self.selcx.infcx.deeply_resolve_ignoring_regions(obligation.predicate); } let obligation = &pending_obligation.obligation; @@ -903,7 +904,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> { debug!( "process_predicate: pending obligation {:?} now stalled on {:?}", - infcx.resolve_vars_if_possible(obligation.clone()), + infcx.deeply_resolve_ignoring_regions(obligation.clone()), stalled_on ); @@ -954,13 +955,15 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> { } ProjectAndUnifyResult::Holds(os) => { let input_projection_term = infcx - .resolve_vars_if_possible(project_obligation.predicate) + .deeply_resolve_ignoring_regions(project_obligation.predicate) .map_bound(|p| p.projection_term); let all_same_projection_term = os.iter().all(|o| { let Some(proj_clause) = o.predicate.as_projection_clause() else { return false; }; - infcx.resolve_vars_if_possible(proj_clause).map_bound(|p| p.projection_term) + infcx + .deeply_resolve_ignoring_regions(proj_clause) + .map_bound(|p| p.projection_term) == input_projection_term }); if all_same_projection_term { @@ -1029,7 +1032,7 @@ fn args_infer_vars<'tcx>( ) -> impl Iterator { selcx .infcx - .resolve_vars_if_possible(args) + .deeply_resolve_ignoring_regions(args) .skip_binder() // ok because this check doesn't care about regions .iter() .filter(|arg| arg.has_non_region_infer()) diff --git a/compiler/rustc_trait_selection/src/traits/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/implied_outlives_bounds.rs index c0df53db4ab34..286de7bed0db8 100644 --- a/compiler/rustc_trait_selection/src/traits/implied_outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/implied_outlives_bounds.rs @@ -64,7 +64,7 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>( continue; } - let arg = ocx.infcx.resolve_vars_if_possible(arg); + let arg = ocx.infcx.deeply_resolve_ignoring_regions(arg); // From the full set of obligations, just filter down to the region relationships. for obligation in wf::unnormalized_obligations(ocx.infcx, param_env, arg, DUMMY_SP, CRATE_DEF_ID) diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 7357d1738d8c3..aa676dab91bbc 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -232,7 +232,8 @@ fn pred_known_to_hold_modulo_regions<'tcx>( // is not smart enough, so we fall back to fulfillment when we're not certain // that an obligation holds or not. Even still, we must make sure that // the we do no inference in the process of checking this obligation. - let goal = infcx.resolve_vars_if_possible((obligation.predicate, obligation.param_env)); + let goal = + infcx.deeply_resolve_ignoring_regions((obligation.predicate, obligation.param_env)); infcx.probe(|_| { let ocx = ObligationCtxt::new(infcx); ocx.register_obligation(obligation); @@ -240,7 +241,7 @@ fn pred_known_to_hold_modulo_regions<'tcx>( let errors = ocx.evaluate_obligations_error_on_ambiguity(); match errors { // Only known to hold if we did no inference. - TraitErrors::NoErrors => infcx.resolve_vars_if_possible(goal) == goal, + TraitErrors::NoErrors => infcx.deeply_resolve_ignoring_regions(goal) == goal, TraitErrors::HasErrors(errors) => { debug!(?errors); @@ -405,7 +406,7 @@ fn do_normalize_clauses<'tcx>( // caller sites. We should also avoid cloning if possible. let normalized_env = ty::ParamEnv::new(tcx, clauses.iter().copied()); let _errors = infcx.resolve_regions(cause.body_def_id, normalized_env, []); - match infcx.fully_resolve(clauses.clone()) { + match infcx.deeply_resolve_via_region_graph(clauses.clone()) { Ok(clauses) => clauses, Err(fixup_err) => { // The first folder only replaces infers from normalization failure. We might not have @@ -631,7 +632,7 @@ pub fn try_evaluate_const<'tcx, E: Debug>( normalize_ty: impl FnOnce(Unnormalized<'tcx, Ty<'tcx>>) -> Result, E>, ) -> Result, EvaluateConstErr> { let tcx = infcx.tcx; - let ct = infcx.resolve_vars_if_possible(ct); + let ct = infcx.deeply_resolve_ignoring_regions(ct); debug!(?ct); match ct.kind() { diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index 2d2c4ff38acee..d52dd8c98d91d 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -78,7 +78,7 @@ impl<'tcx> At<'_, 'tcx> { .normalize(value) .into_value_registering_obligations(self.infcx, &mut *fulfill_cx); let errors = fulfill_cx.evaluate_obligations_error_on_ambiguity(self.infcx); - let value = self.infcx.resolve_vars_if_possible(value); + let value = self.infcx.deeply_resolve_ignoring_regions(value); match errors { TraitErrors::NoErrors => Ok(value), TraitErrors::HasErrors(errors) => { @@ -171,7 +171,7 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { } fn fold>>(&mut self, value: T) -> T { - let value = self.selcx.infcx.resolve_vars_if_possible(value); + let value = self.selcx.infcx.deeply_resolve_ignoring_regions(value); debug!(?value); assert!( diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs index 84cae1e7bfa0a..8a464bfcf1024 100644 --- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs @@ -1,6 +1,6 @@ use rustc_infer::infer::InferOk; use rustc_infer::infer::canonical::QueryRegionConstraint; -use rustc_infer::infer::resolve::OpportunisticRegionResolver; +use rustc_infer::infer::resolve::DeepRegionResolver; use rustc_infer::traits::query::type_op::ImpliedOutlivesBounds; use rustc_macros::extension; use rustc_middle::infer::canonical::{OriginalQueryValues, QueryRegionConstraints}; @@ -39,8 +39,8 @@ fn implied_outlives_bounds<'a, 'tcx>( ty: Ty<'tcx>, disable_implied_bounds_hack: bool, ) -> Vec> { - let ty = infcx.resolve_vars_if_possible(ty); - let ty = OpportunisticRegionResolver::new(infcx).fold_ty(ty); + let ty = infcx.deeply_resolve_ignoring_regions(ty); + let ty = DeepRegionResolver::new(infcx).fold_ty(ty); // We do not expect existential variables in implied bounds. // We may however encounter unconstrained lifetime variables diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index f3504e96965e8..496ddbfebd4f0 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -7,7 +7,7 @@ use rustc_errors::ErrorGuaranteed; use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::DefId; use rustc_infer::infer::DefineOpaqueTypes; -use rustc_infer::infer::resolve::OpportunisticRegionResolver; +use rustc_infer::infer::resolve::DeepRegionResolver; use rustc_infer::traits::{ObligationCauseCode, PredicateObligations}; use rustc_middle::traits::select::OverflowError; use rustc_middle::traits::{BuiltinImplSource, ImplSource, ImplSourceUserDefinedData}; @@ -309,7 +309,7 @@ pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>( ) -> Result>, InProgress> { let infcx = selcx.infcx; debug_assert!(!selcx.infcx.next_trait_solver()); - let projection_term = infcx.resolve_vars_if_possible(projection_term); + let projection_term = infcx.deeply_resolve_ignoring_regions(projection_term); let cache_key = ProjectionCacheKey::new(projection_term, param_env); // FIXME(#20304) For now, I am caching here, which is good, but it @@ -388,7 +388,7 @@ pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>( // an impl, where-clause etc) and hence we must // re-normalize it - let projected_term = selcx.infcx.resolve_vars_if_possible(projected_term); + let projected_term = selcx.infcx.deeply_resolve_ignoring_regions(projected_term); let mut result = if projected_term.has_aliases() { let normalized_ty = normalize_with_depth_to( @@ -584,7 +584,7 @@ pub fn normalize_inherent_projection<'a, 'b, 'tcx>( const_of_item_or_delayed_bug(tcx, def_id).instantiate(tcx, args).map(Into::into) }; - let term = selcx.infcx.resolve_vars_if_possible(term); + let term = selcx.infcx.deeply_resolve_ignoring_regions(term); let term = normalize_with_depth_to(selcx, param_env, cause.clone(), depth + 1, term, obligations); @@ -1053,7 +1053,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( // NOTE(eddyb) inference variables can resolve to parameters, so // assume `poly_trait_ref` isn't monomorphic, if it contains any. let poly_trait_ref = - selcx.infcx.resolve_vars_if_possible(trait_ref); + selcx.infcx.deeply_resolve_ignoring_regions(trait_ref); !poly_trait_ref.still_further_specializable() } } @@ -1326,7 +1326,7 @@ fn confirm_candidate<'cx, 'tcx>( if let Ok(Projected::Progress(progress)) = &mut result && progress.term.has_infer_regions() { - progress.term = progress.term.fold_with(&mut OpportunisticRegionResolver::new(selcx.infcx)); + progress.term = progress.term.fold_with(&mut DeepRegionResolver::new(selcx.infcx)); } result @@ -2221,7 +2221,7 @@ impl<'cx, 'tcx> ProjectionCacheKeyExt<'cx, 'tcx> for ProjectionCacheKey<'tcx> { // from a specific call to `opt_normalize_projection_type` - if // there's no precise match, the original cache entry is "stranded" // anyway. - infcx.resolve_vars_if_possible(predicate.projection_term), + infcx.deeply_resolve_ignoring_regions(predicate.projection_term), obligation.param_env, ) }) diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs index 25385d15e36f4..651c872cd9072 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs @@ -140,7 +140,7 @@ where })?; // Next trait solver performs operations locally, and normalize goals should resolve vars. - let value = infcx.resolve_vars_if_possible(value); + let value = infcx.deeply_resolve_ignoring_regions(value); let region_obligations = infcx.take_registered_region_obligations(); let region_assumptions = infcx.take_registered_region_assumptions(); diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 30700689a8ff0..bd61bcc7f4d07 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -38,7 +38,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { param_env: obligation.param_env, cause: obligation.cause.clone(), recursion_depth: obligation.recursion_depth, - predicate: self.infcx.resolve_vars_if_possible(obligation.predicate), + predicate: self.infcx.deeply_resolve_ignoring_regions(obligation.predicate), }; if obligation.predicate.skip_binder().self_ty().is_ty_var() { @@ -209,7 +209,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } self.infcx.probe(|_| { - let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate); + let poly_trait_predicate = + self.infcx.deeply_resolve_ignoring_regions(obligation.predicate); let placeholder_trait_predicate = self.infcx.enter_forall_and_leak_universe(poly_trait_predicate); @@ -927,7 +928,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } self.infcx.probe(|_snapshot| { - let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate); + let poly_trait_predicate = + self.infcx.deeply_resolve_ignoring_regions(obligation.predicate); self.infcx.enter_forall(poly_trait_predicate, |placeholder_trait_predicate| { let self_ty = placeholder_trait_predicate.self_ty(); let principal_trait_ref = match self_ty.kind() { @@ -1373,7 +1375,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &PolyTraitObligation<'tcx>, candidates: &mut SelectionCandidateSet<'tcx>, ) { - let self_ty = self.infcx.resolve_vars_if_possible(obligation.self_ty()); + let self_ty = self.infcx.deeply_resolve_ignoring_regions(obligation.self_ty()); match self_ty.skip_binder().kind() { ty::FnPtr(..) => candidates.vec.push(BuiltinCandidate), diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 15dfd58d6b753..a9ac96424d018 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -379,7 +379,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } if !candidate_set.ambiguous && no_candidates_apply { - let trait_ref = self.infcx.resolve_vars_if_possible( + let trait_ref = self.infcx.deeply_resolve_ignoring_regions( stack.obligation.predicate.skip_binder().trait_ref, ); if !trait_ref.references_error() { @@ -508,15 +508,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) -> Result { debug_assert!(!self.infcx.next_trait_solver()); self.evaluation_probe(|this| { - let goal = - this.infcx.resolve_vars_if_possible((obligation.predicate, obligation.param_env)); + let goal = this + .infcx + .deeply_resolve_ignoring_regions((obligation.predicate, obligation.param_env)); let mut result = this.evaluate_predicate_recursively( TraitObligationStackList::empty(&ProvisionalEvaluationCache::default()), obligation.clone(), )?; // If the predicate has done any inference, then downgrade the // result to ambiguous. - if this.infcx.resolve_vars_if_possible(goal) != goal { + if this.infcx.deeply_resolve_ignoring_regions(goal) != goal { result = result.max(EvaluatedToAmbig); } Ok(result) @@ -1445,7 +1446,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!("is_knowable()"); - let predicate = self.infcx.resolve_vars_if_possible(obligation.predicate); + let predicate = self.infcx.deeply_resolve_ignoring_regions(obligation.predicate); // Okay to skip binder because of the nature of the // trait-ref-is-knowable check, which does not care about @@ -2470,7 +2471,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { match self.match_impl(impl_def_id, impl_trait_header, obligation) { Ok(args) => args, Err(()) => { - let predicate = self.infcx.resolve_vars_if_possible(obligation.predicate); + let predicate = self.infcx.deeply_resolve_ignoring_regions(obligation.predicate); bug!("impl {impl_def_id:?} was matchable against {predicate:?} but now is not") } } diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index f7351a6b8ed36..9a0894891f625 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -215,7 +215,7 @@ fn fulfill_implication<'tcx>( // Now resolve the *generic parameters* we built for the target earlier, replacing // the inference variables inside with whatever we got from fulfillment. - Ok(infcx.resolve_vars_if_possible(target_args)) + Ok(infcx.deeply_resolve_ignoring_regions(target_args)) } pub(super) fn specialization_enabled_in(tcx: TyCtxt<'_>, _: LocalCrate) -> bool { diff --git a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs index e5fff1eb0fd04..2313ceaabd1ca 100644 --- a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs @@ -69,7 +69,7 @@ impl<'tcx> At<'_, 'tcx> { return Err(errors); } - Ok(self.infcx.resolve_vars_if_possible(new_infer)) + Ok(self.infcx.deeply_resolve_ignoring_regions(new_infer)) } else { Ok(self.normalize(term).into_value_registering_obligations(self.infcx, fulfill_cx)) } diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 632e805388eb6..9045d9a644ac0 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -98,7 +98,7 @@ pub fn unnormalized_obligations<'tcx>( span: Span, body_def_id: LocalDefId, ) -> Option> { - debug_assert_eq!(term, infcx.resolve_vars_if_possible(term)); + debug_assert_eq!(term, infcx.deeply_resolve_ignoring_regions(term)); // However, if `term` IS an unresolved inference variable, returns `None`, // because we are not able to make any progress at all. This is to prevent diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs index e03b67f8e4d39..006e793b7a5eb 100644 --- a/compiler/rustc_traits/src/codegen.rs +++ b/compiler/rustc_traits/src/codegen.rs @@ -72,7 +72,7 @@ pub(crate) fn codegen_select_candidate<'tcx>( return Err(CodegenObligationError::Unimplemented); } - let impl_source = infcx.resolve_vars_if_possible(impl_source); + let impl_source = infcx.deeply_resolve_ignoring_regions(impl_source); let impl_source = tcx.erase_and_anonymize_regions(impl_source); if impl_source.has_non_region_infer() { // Unused generic types or consts on an impl get replaced with inference vars, diff --git a/compiler/rustc_traits/src/coroutine_witnesses.rs b/compiler/rustc_traits/src/coroutine_witnesses.rs index 762471eefe4dd..c3e4bfdb45e3a 100644 --- a/compiler/rustc_traits/src/coroutine_witnesses.rs +++ b/compiler/rustc_traits/src/coroutine_witnesses.rs @@ -1,7 +1,7 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::canonical::QueryRegionConstraint; use rustc_infer::infer::canonical::query_response::make_query_region_constraints; -use rustc_infer::infer::resolve::OpportunisticRegionResolver; +use rustc_infer::infer::resolve::DeepRegionResolver; use rustc_infer::traits::{Obligation, ObligationCause}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, fold_regions}; use rustc_span::def_id::DefId; @@ -86,7 +86,7 @@ fn compute_assumptions<'tcx>( region_assumptions, ) .constraints - .fold_with(&mut OpportunisticRegionResolver::new(&infcx)); + .fold_with(&mut DeepRegionResolver::new(&infcx)); tcx.mk_outlives_from_iter( constraints diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs index 1ba385e86b310..5ee83ae651713 100644 --- a/compiler/rustc_traits/src/normalize_erasing_regions.rs +++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs @@ -36,7 +36,7 @@ fn try_normalize_after_erasing_regions<'tcx, T: TypeFoldable> + Par None, ); - let resolved_value = infcx.resolve_vars_if_possible(normalized_value); + let resolved_value = infcx.deeply_resolve_ignoring_regions(normalized_value); // It's unclear when `resolve_vars` would have an effect in a // fresh `InferCtxt`. If this assert does trigger, it will give // us a test case. diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index 8d1d3372fac69..a86a07edb902f 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -423,25 +423,19 @@ pub trait InferCtxtLike: Sized { ); fn universe_of_ty(&self, ty: ty::TyVid) -> Option; - fn universe_of_lt(&self, lt: ty::RegionVid) -> Option; - fn universe_of_ct(&self, ct: ty::ConstVid) -> Option; + fn universe_of_region(&self, lt: ty::RegionVid) -> Option; + fn universe_of_const(&self, ct: ty::ConstVid) -> Option; fn root_ty_var(&self, var: ty::TyVid) -> ty::TyVid; fn sub_unification_table_root_var(&self, var: ty::TyVid) -> ty::TyVid; fn is_sub_unification_table_root_var(&self, var: ty::TyVid) -> bool; fn root_const_var(&self, var: ty::ConstVid) -> ty::ConstVid; - fn opportunistic_resolve_ty_var(&self, vid: ty::TyVid) -> ::Ty; - fn opportunistic_resolve_int_var(&self, vid: ty::IntVid) -> ::Ty; - fn opportunistic_resolve_float_var( - &self, - vid: ty::FloatVid, - ) -> ::Ty; - fn opportunistic_resolve_ct_var( - &self, - vid: ty::ConstVid, - ) -> ::Const; - fn opportunistic_resolve_lt_var(&self, vid: ty::RegionVid) -> Region; + fn shallow_resolve_ty_var(&self, vid: ty::TyVid) -> ::Ty; + fn shallow_resolve_int_var(&self, vid: ty::IntVid) -> ::Ty; + fn shallow_resolve_float_var(&self, vid: ty::FloatVid) -> ::Ty; + fn shallow_resolve_const_var(&self, vid: ty::ConstVid) -> ::Const; + fn shallow_resolve_region_var(&self, vid: ty::RegionVid) -> Region; fn ty_or_const_infer_var_changed(&self, var: TyOrConstInferVar) -> bool; @@ -514,7 +508,7 @@ pub trait InferCtxtLike: Sized { ty: ::Const, ) -> ::Const; - fn resolve_vars_if_possible(&self, value: T) -> T + fn deeply_resolve_ignoring_regions(&self, value: T) -> T where T: TypeFoldable; @@ -582,6 +576,20 @@ pub trait InferCtxtLike: Sized { ); fn reset_opaque_types(&self); + + /// Where possible, replaces type/const/region variables in `value` with their final value. + /// If a type/const/region variable has not (yet) been unified, it is left as is. + /// + /// This is an idempotent operation that does not affect inference state in any way, + /// which means it's safe to call this function at will. + fn deeply_resolve_via_unification_table>(&self, value: T) -> T { + if value.has_infer() { + let mut folder = DeepVariableResolver::new(self); + value.fold_with(&mut folder) + } else { + value + } + } } pub fn may_use_unstable_feature<'a, I: Interner, Infcx>( @@ -628,20 +636,7 @@ where } } -/// Resolves ty, region, and const vars to their inferred values or their root vars. -pub fn eager_resolve_vars>( - infcx: &Infcx, - value: T, -) -> T { - if value.has_infer() { - let mut folder = EagerResolver::new(infcx); - value.fold_with(&mut folder) - } else { - value - } -} - -struct EagerResolver<'a, D, I = ::Interner> +struct DeepVariableResolver<'a, D, I = ::Interner> where D: InferCtxtLike, I: Interner, @@ -652,13 +647,15 @@ where cache: DelayedMap, } -impl<'a, Infcx: InferCtxtLike> EagerResolver<'a, Infcx> { +impl<'a, Infcx: InferCtxtLike> DeepVariableResolver<'a, Infcx> { fn new(delegate: &'a Infcx) -> Self { - EagerResolver { delegate, cache: Default::default() } + DeepVariableResolver { delegate, cache: Default::default() } } } -impl, I: Interner> TypeFolder for EagerResolver<'_, Infcx> { +impl, I: Interner> TypeFolder + for DeepVariableResolver<'_, Infcx> +{ fn cx(&self) -> I { self.delegate.cx() } @@ -666,15 +663,15 @@ impl, I: Interner> TypeFolder for EagerRes fn fold_ty(&mut self, t: I::Ty) -> I::Ty { match t.kind() { ty::Infer(ty::TyVar(vid)) => { - let resolved = self.delegate.opportunistic_resolve_ty_var(vid); + let resolved = self.delegate.shallow_resolve_ty_var(vid); if t != resolved && resolved.has_infer() { resolved.fold_with(self) } else { resolved } } - ty::Infer(ty::IntVar(vid)) => self.delegate.opportunistic_resolve_int_var(vid), - ty::Infer(ty::FloatVar(vid)) => self.delegate.opportunistic_resolve_float_var(vid), + ty::Infer(ty::IntVar(vid)) => self.delegate.shallow_resolve_int_var(vid), + ty::Infer(ty::FloatVar(vid)) => self.delegate.shallow_resolve_float_var(vid), _ => { if t.has_infer() { if let Some(&ty) = self.cache.get(&t) { @@ -692,7 +689,7 @@ impl, I: Interner> TypeFolder for EagerRes fn fold_region(&mut self, r: Region) -> Region { match r.kind() { - ty::ReVar(vid) => self.delegate.opportunistic_resolve_lt_var(vid), + ty::ReVar(vid) => self.delegate.shallow_resolve_region_var(vid), _ => r, } } @@ -700,7 +697,7 @@ impl, I: Interner> TypeFolder for EagerRes fn fold_const(&mut self, c: I::Const) -> I::Const { match c.kind() { ty::ConstKind::Infer(ty::InferConst::Var(vid)) => { - let resolved = self.delegate.opportunistic_resolve_ct_var(vid); + let resolved = self.delegate.shallow_resolve_const_var(vid); if c != resolved && resolved.has_infer() { resolved.fold_with(self) } else { diff --git a/compiler/rustc_type_ir/src/relate/combine.rs b/compiler/rustc_type_ir/src/relate/combine.rs index 29193f40959d3..7b747141889fe 100644 --- a/compiler/rustc_type_ir/src/relate/combine.rs +++ b/compiler/rustc_type_ir/src/relate/combine.rs @@ -243,7 +243,7 @@ where ty::Bivariant => { let has_non_region_infer = |arg: I::GenericArg| { arg.has_non_region_infer() - && infcx.resolve_vars_if_possible(arg).has_non_region_infer() + && infcx.deeply_resolve_ignoring_regions(arg).has_non_region_infer() }; if has_non_region_infer(a) || has_non_region_infer(b) { has_unconstrained_bivariant_arg = true; diff --git a/compiler/rustc_type_ir/src/universe.rs b/compiler/rustc_type_ir/src/universe.rs index a5a4b2c02be89..1f38edd78023d 100644 --- a/compiler/rustc_type_ir/src/universe.rs +++ b/compiler/rustc_type_ir/src/universe.rs @@ -57,7 +57,7 @@ fn max_universe_inner< let mut visitor = MaxUniverse::<_, _, VISIT_PLACEHOLDER, VISIT_INFER>::new(infcx); // FIXME: make this a debug_assert and let callers resolve vars. Then the input only needs to // be `TypeVisitable`. - let t = infcx.resolve_vars_if_possible(t); + let t = infcx.deeply_resolve_ignoring_regions(t); t.visit_with(&mut visitor); visitor.max_universe() } @@ -140,7 +140,7 @@ impl< self.max_universe = self.max_universe.max(p.universe) } ConstKind::Infer(rustc_type_ir::InferConst::Var(inf)) if VISIT_INFER => { - let u = self.infcx.universe_of_ct(inf).unwrap(); + let u = self.infcx.universe_of_const(inf).unwrap(); debug!("var {inf:?} in universe {u:?}"); self.max_universe = self.max_universe.max(u); } @@ -154,12 +154,12 @@ impl< self.max_universe = self.max_universe.max(p.universe) } RegionKind::ReVar(var) if VISIT_INFER => { - match self.infcx.opportunistic_resolve_lt_var(var).kind() { + match self.infcx.shallow_resolve_region_var(var).kind() { RegionKind::RePlaceholder(p) if VISIT_PLACEHOLDER => { self.max_universe = self.max_universe.max(p.universe) } RegionKind::ReVar(var) if VISIT_INFER => { - let u = self.infcx.universe_of_lt(var).unwrap(); + let u = self.infcx.universe_of_region(var).unwrap(); debug!("var {var:?} in universe {u:?}"); self.max_universe = self.max_universe.max(u); } diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index b6bf18a155051..c91e6961f9123 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -25,7 +25,9 @@ are documented at our [Forge documentation site][forge]. Tier 1 targets can be thought of as "guaranteed to work". The Rust project builds official binary releases for each tier 1 target, and automated testing -ensures that each tier 1 target builds and passes tests after each change. +ensures that each tier 1 target builds and passes tests after each change. For +the full requirements, see [Tier 1 target +policy](target-tier-policy.md#tier-1-target-policy) in the Target Tier Policy. Tier 1 targets with host tools additionally support running tools like `rustc` and `cargo` natively on the target, and automated testing ensures that tests @@ -34,19 +36,17 @@ development platform, not just a compilation target. For the full requirements, see [Tier 1 with Host Tools](target-tier-policy.md#tier-1-with-host-tools) in the Target Tier Policy. -All tier 1 targets with host tools support the full standard library. +All tier 1 (with host tools) targets support the full standard library. target | notes -------|------- [`aarch64-apple-darwin`](platform-support/apple-darwin.md) | ARM64 macOS (11.0+, Big Sur+) [`aarch64-pc-windows-msvc`](platform-support/windows-msvc.md) | ARM64 Windows MSVC [`aarch64-unknown-linux-gnu`](platform-support/aarch64-unknown-linux-gnu.md) | ARM64 Linux (kernel 4.1+, glibc 2.17+) -[`i686-pc-windows-msvc`](platform-support/windows-msvc.md) | 32-bit MSVC (Windows 10+, Windows Server 2016+, Pentium 4) [^x86_32-floats-return-ABI] [^win32-msvc-alignment] `i686-unknown-linux-gnu` | 32-bit Linux (kernel 3.2+, glibc 2.17+, Pentium 4) [^x86_32-floats-return-ABI] [`x86_64-pc-windows-gnu`](platform-support/windows-gnu.md) | 64-bit MinGW (Windows 10+, Windows Server 2016+) [`x86_64-pc-windows-msvc`](platform-support/windows-msvc.md) | 64-bit MSVC (Windows 10+, Windows Server 2016+) `x86_64-unknown-linux-gnu` | 64-bit Linux (kernel 3.2+, glibc 2.17+) - [^x86_32-floats-return-ABI]: Due to limitations of the C ABI, floating-point support on `i686` targets is non-compliant: floating-point return values are passed via an x87 register, so NaN payload bits can be lost. Functions with the default Rust ABI are not affected. See [issue #115567][x86-32-float-return-issue]. [^win32-msvc-alignment]: Due to non-standard behavior of MSVC, native C code on this target can cause types with an alignment of more than 4 bytes to be incorrectly aligned to only 4 bytes (this affects, e.g., `u64` and `i64`). Rust applies some mitigations to reduce the impact of this issue, but this can still cause unsoundness due to unsafe code that (correctly) assumes that references are always properly aligned. See [issue #112480](https://github.com/rust-lang/rust/issues/112480). @@ -54,16 +54,13 @@ target | notes [77071]: https://github.com/rust-lang/rust/issues/77071 [x86-32-float-return-issue]: https://github.com/rust-lang/rust/issues/115567 -## Tier 1 +## Tier 1 without Host Tools -Tier 1 targets can be thought of as "guaranteed to work". The Rust project -builds official binary releases for each tier 1 target, and automated testing -ensures that each tier 1 target builds and passes tests after each change. For -the full requirements, see [Tier 1 target -policy](target-tier-policy.md#tier-1-target-policy) in the Target Tier Policy. +target | notes +-------|------- +[`i686-pc-windows-msvc`](platform-support/windows-msvc.md) | 32-bit MSVC (Windows 10+, Windows Server 2016+, Pentium 4) [^x86_32-floats-return-ABI] [^win32-msvc-alignment] -At this time, all Tier 1 targets are [Tier 1 with Host -Tools](#tier-1-with-host-tools). +All tier 1 (without host tools) targets support the full standard library. ## Tier 2 with Host Tools @@ -421,7 +418,7 @@ target | std | host | notes [`riscv64-oe-linux-gnu`](platform-support/oe-linux-gnu.md) | ✓ | | RISC-V OpenEmbedded/Yocto Linux (GNU) [`riscv64-wrs-vxworks`](platform-support/vxworks.md) | ✓ | | `riscv64gc-unknown-freebsd` | ? | | RISC-V FreeBSD -`riscv64gc-unknown-fuchsia` | ? | | RISC-V Fuchsia +[`riscv64gc-unknown-fuchsia`](platform-support/fuchsia.md) | ✓ | | RISC-V Fuchsia [`riscv64gc-unknown-hermit`](platform-support/hermit.md) | ✓ | | RISC-V Hermit [`riscv64gc-unknown-managarm-mlibc`](platform-support/managarm.md) | ? | | RISC-V Managarm [`riscv64gc-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | RISC-V NetBSD diff --git a/src/doc/rustc/src/platform-support/fuchsia.md b/src/doc/rustc/src/platform-support/fuchsia.md index e2befc5d9955b..2ce9916003393 100644 --- a/src/doc/rustc/src/platform-support/fuchsia.md +++ b/src/doc/rustc/src/platform-support/fuchsia.md @@ -7,8 +7,11 @@ updatable, and performant. ## Target maintainers -[@erickt](https://github.com/erickt) -[@Nashenas88](https://github.com/Nashenas88) +- [@Nashenas88](https://github.com/Nashenas88) +- [@PiJoules](https://github.com/PiJoules) +- [@erickt](https://github.com/erickt) +- [@ilovepi](https://github.com/ilovepi) +- [@petrhosek](https://github.com/petrhosek) The up-to-date list can be also found via the [fuchsia marker team](https://github.com/rust-lang/team/blob/master/teams/fuchsia.toml). @@ -181,12 +184,12 @@ Before building Rust for Fuchsia, you'll need a clang toolchain that supports Fuchsia as well. A recent version (14+) of clang should be sufficient to compile Rust for Fuchsia. -x86-64 and AArch64 Fuchsia targets can be enabled using the following +x86-64, AArch64, and riscv64gc Fuchsia targets can be enabled using the following configuration in `bootstrap.toml`: ```toml [build] -target = ["", "aarch64-unknown-fuchsia", "x86_64-unknown-fuchsia"] +target = ["", "aarch64-unknown-fuchsia", "x86_64-unknown-fuchsia", "riscv64gc-unknown-fuchsia"] [rust] lld = true @@ -201,6 +204,10 @@ cxx = "clang++" [target.aarch64-unknown-fuchsia] cc = "clang" cxx = "clang++" + +[target.riscv64gc-unknown-fuchsia] +cc = "clang" +cxx = "clang++" ``` Though not strictly required, you may also want to use `clang` for your host @@ -237,6 +244,10 @@ export CFLAGS_x86_64_unknown_fuchsia="--target=x86_64-unknown-fuchsia --sysroot= export CXXFLAGS_x86_64_unknown_fuchsia="--target=x86_64-unknown-fuchsia --sysroot=${SDK_PATH}/arch/x64/sysroot -I${SDK_PATH}/pkg/fdio/include" export LDFLAGS_x86_64_unknown_fuchsia="--target=x86_64-unknown-fuchsia --sysroot=${SDK_PATH}/arch/x64/sysroot -L${SDK_PATH}/arch/x64/lib" export CARGO_TARGET_X86_64_UNKNOWN_FUCHSIA_RUSTFLAGS="-C link-arg=--sysroot=${SDK_PATH}/arch/x64/sysroot -Lnative=${SDK_PATH}/arch/x64/sysroot/lib -Lnative=${SDK_PATH}/arch/x64/lib" +export CFLAGS_riscv64gc_unknown_fuchsia="--target=riscv64gc-unknown-fuchsia --sysroot=${SDK_PATH}/arch/riscv64/sysroot -I${SDK_PATH}/pkg/fdio/include" +export CXXFLAGS_riscv64gc_unknown_fuchsia="--target=riscv64gc-unknown-fuchsia --sysroot=${SDK_PATH}/arch/riscv64/sysroot -I${SDK_PATH}/pkg/fdio/include" +export LDFLAGS_riscv64gc_unknown_fuchsia="--target=riscv64gc-unknown-fuchsia --sysroot=${SDK_PATH}/arch/riscv64/sysroot -L${SDK_PATH}/arch/riscv64/lib" +export CARGO_TARGET_RISCV64GC_UNKNOWN_FUCHSIA_RUSTFLAGS="-C link-arg=--sysroot=${SDK_PATH}/arch/riscv64/sysroot -Lnative=${SDK_PATH}/arch/riscv64/sysroot/lib -Lnative=${SDK_PATH}/arch/riscv64/lib" ``` Finally, the Rust compiler can be built and installed: @@ -281,8 +292,9 @@ hello_fuchsia/ Using your freshly installed `rustc`, you can compile a binary for Fuchsia using the following options: -* `--target x86_64-unknown-fuchsia`/`--target aarch64-unknown-fuchsia`: Targets the Fuchsia - platform of your choice +* `--target x86_64-unknown-fuchsia` / `--target aarch64-unknown-fuchsia` / + `--target riscv64gc-unknown-fuchsia`: Targets the Fuchsia platform of your + choice * `-Lnative ${SDK_PATH}/arch/${ARCH}/lib`: Link against Fuchsia libraries from the SDK * `-Lnative ${SDK_PATH}/arch/${ARCH}/sysroot/lib`: Link against Fuchsia sysroot @@ -292,8 +304,8 @@ Putting it all together: ```sh # Configure these for the Fuchsia target of your choice -TARGET_ARCH="" -ARCH="" +TARGET_ARCH="" +ARCH="" rustc \ --target ${TARGET_ARCH} \ @@ -688,12 +700,12 @@ We can then use the script to start our test environment with: ```sh ( \ - source config-env.sh && \ - src/ci/docker/scripts/fuchsia-test-runner.py start \ - --rust-build ${RUST_SRC_PATH}/build \ - --sdk ${SDK_PATH} \ - --target {x86_64-unknown-fuchsia|aarch64-unknown-fuchsia} \ - --verbose \ + source config-env.sh && \ + src/ci/docker/scripts/fuchsia-test-runner.py start \ + --rust-build ${RUST_SRC_PATH}/build \ + --sdk ${SDK_PATH} \ + --target {x86_64-unknown-fuchsia|aarch64-unknown-fuchsia|riscv64gc-unknown-fuchsia} \ + --verbose \ ) ``` @@ -707,7 +719,7 @@ run the full `tests/ui` test suite: ( \ source config-env.sh && \ ./x.py \ - --config bootstrap.toml \ + --config bootstrap.toml \ --stage=2 \ test tests/ui \ --target x86_64-unknown-fuchsia \ diff --git a/src/doc/rustc/src/platform-support/windows-msvc.md b/src/doc/rustc/src/platform-support/windows-msvc.md index c4b56201e7968..266a427ae9618 100644 --- a/src/doc/rustc/src/platform-support/windows-msvc.md +++ b/src/doc/rustc/src/platform-support/windows-msvc.md @@ -5,9 +5,11 @@ Windows MSVC targets. **Tier 1 with host tools:** - `aarch64-pc-windows-msvc`: Windows on ARM64. -- `i686-pc-windows-msvc`: Windows on 32-bit x86. - `x86_64-pc-windows-msvc`: Windows on 64-bit x86. +**Tier 1 without host tools:** +- `i686-pc-windows-msvc`: Windows on 32-bit x86. + ## Target maintainers [@ChrisDenton](https://github.com/ChrisDenton) @@ -26,7 +28,9 @@ Windows 10 or higher is required for client installs, Windows Server 2016 or hig ### Host tooling The minimum supported Visual Studio version is 2017 but this support is not actively tested in CI. -It is **highly** recommended to use the latest version of VS (currently VS 2022). +It is **highly** recommended to use the latest version of VS (currently VS 2026). + +Only 64-bit `*-pc-windows-msvc` targets support host tools. ### Platform details diff --git a/src/doc/unstable-book/src/language-features/macroless-const-item-generic-const-args.md b/src/doc/unstable-book/src/language-features/macroless-const-item-generic-const-args.md new file mode 100644 index 0000000000000..d208d3243229d --- /dev/null +++ b/src/doc/unstable-book/src/language-features/macroless-const-item-generic-const-args.md @@ -0,0 +1,74 @@ +# macroless_generic_const_args + +Enables implementing const items under `#![feature(min_generic_const_args)]` and `#![feature(generic_const_args)]` without the `direct_const_arg!` macro. + +The tracking issue for this feature is: [#162540] + +[#162540]: https://github.com/rust-lang/rust/issues/162540 + +------------------------ + +Warning: This feature is incomplete; its design and syntax may change. + +Related features: +- [min_generic_const_args]. See that doc for what the `direct_const_arg!` is. This feature enables +support for directly represented const arguments as the rhs of const items without the macro. +- [macroless_generic_const_args]. For a version of this feature that works for const arguments in other +positions + +[min_generic_const_args]: min-generic-const-args.md +[macroless_generic_const_args]: macroless-generic-const-args.md + +## Examples + +Here is an example from [min_generic_const_args]: + +[min_generic_const_args]: min-generic-const-args.md + +```rust,ignore (needs new solver) +#![allow(incomplete_features)] +#![feature( + min_generic_const_args, + generic_const_args, + macroless_generic_const_args, + generic_const_items, +)] + +trait Trait { + const ASSOC: usize; +} + +impl Trait for () { + const ASSOC: usize = core::direct_const_arg!(N); +} + +fn foo() { + let a: [(); <() as Trait>::ASSOC::] + = [(); N]; +} +``` + +Using `#![feature(macroless_const_item_generic_const_args)]` enables you to write the above without the macro: + +```rust,ignore (needs new solver) +#![allow(incomplete_features)] +#![feature( + min_generic_const_args, + generic_const_args, + macroless_generic_const_args, + generic_const_items, +)] + +trait Trait { + const ASSOC: usize; +} + +impl Trait for () { + const ASSOC: usize = N; +} + +fn foo() { + let a: [(); <() as Trait>::ASSOC::] + = [(); N]; +} +``` diff --git a/src/doc/unstable-book/src/language-features/macroless-generic-const-args.md b/src/doc/unstable-book/src/language-features/macroless-generic-const-args.md index 18f4e5cd97a98..6b1205a006d0f 100644 --- a/src/doc/unstable-book/src/language-features/macroless-generic-const-args.md +++ b/src/doc/unstable-book/src/language-features/macroless-generic-const-args.md @@ -10,10 +10,14 @@ The tracking issue for this feature is: [#159006] Warning: This feature is incomplete; its design and syntax may change. -Related features: [min_generic_const_args]. See that doc for what the `direct_const_arg!` is. This feature enables +Related features: +- [min_generic_const_args]. See that doc for what the `direct_const_arg!` is. This feature enables support for directly represented const arguments without the macro. +- [macroless_const_item_generic_const_args]. For a version of this feature that works for const arguments +as the right hand side of a const item. [min_generic_const_args]: min-generic-const-args.md +[macroless_const_item_generic_const_args]: macroless-const-item-generic-const-args.md ## Examples diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 2b1a37cbcda30..7f6392fce691a 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1990,7 +1990,7 @@ fn normalize<'tcx>( let normalized = infcx .at(&ObligationCause::dummy(), cx.param_env) .query_normalize(ty) - .map(|resolved| infcx.resolve_vars_if_possible(resolved.value)); + .map(|resolved| infcx.deeply_resolve_ignoring_regions(resolved.value)); match normalized { Ok(normalized_value) => { debug!("normalized {ty:?} to {normalized_value:?}"); diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 13fc6e3bc1bb8..2c42c165243a3 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -432,7 +432,7 @@ fn generate_item_def_id_path( let ty = infcx .at(&ObligationCause::dummy(), tcx.param_env(def_id)) .query_normalize(ty::Binder::dummy(ty.instantiate_identity().skip_norm_wip())) - .map(|resolved| infcx.resolve_vars_if_possible(resolved.value).skip_binder()) + .map(|resolved| infcx.deeply_resolve_ignoring_regions(resolved.value).skip_binder()) .unwrap_or(ty.skip_binder()); if let Some(new_def_id) = ty.ty_adt_def().map(|adt| adt.did()) { def_id = new_def_id; diff --git a/tests/rustdoc-ui/lints/invalid-doc-attr-2.stderr b/tests/rustdoc-ui/lints/invalid-doc-attr-2.stderr index 661b9eae9ce9b..0285af4108ef0 100644 --- a/tests/rustdoc-ui/lints/invalid-doc-attr-2.stderr +++ b/tests/rustdoc-ui/lints/invalid-doc-attr-2.stderr @@ -11,7 +11,7 @@ note: the lint level is defined here LL | #![deny(invalid_doc_attributes)] | ^^^^^^^^^^^^^^^^^^^^^^ -error: valid forms for the attribute are `doc = "string"`, `doc(alias)`, `doc(attribute)`, `doc(auto_cfg)`, `doc(cfg)`, `doc(fake_variadic)`, `doc(hidden)`, `doc(html_favicon_url)`, `doc(html_logo_url)`, `doc(html_no_source)`, `doc(html_playground_url)`, `doc(html_root_url)`, `doc(include)`, `doc(inline)`, `doc(issue_tracker_base_url)`, `doc(keyword)`, `doc(masked)`, `doc(no_default_passes)`, `doc(no_inline)`, `doc(notable_trait)`, `doc(passes)`, `doc(plugins)`, `doc(rust_logo)`, `doc(search_unbox)`, `doc(spotlight)`, and `doc(test)` +error: valid forms for the attribute are `doc = "doc comment"`, `doc(alias)`, `doc(auto_cfg)`, `doc(cfg)`, `doc(hidden)`, `doc(html_favicon_url)`, `doc(html_logo_url)`, `doc(html_no_source)`, `doc(html_playground_url)`, `doc(html_root_url)`, `doc(inline)`, `doc(issue_tracker_base_url)`, `doc(masked)`, `doc(no_inline)`, `doc(notable_trait)`, and `doc(test)` --> $DIR/invalid-doc-attr-2.rs:6:4 | LL | #![doc] diff --git a/tests/ui/attributes/malformed-attrs.rs b/tests/ui/attributes/malformed-attrs.rs index d5f663020f3e0..36ad21a54bd51 100644 --- a/tests/ui/attributes/malformed-attrs.rs +++ b/tests/ui/attributes/malformed-attrs.rs @@ -40,6 +40,8 @@ //~^ ERROR malformed #[doc] //~^ ERROR +#[doc()] +//~^ ERROR #[rustc_macro_transparency] //~^ ERROR malformed //~| ERROR attribute cannot be used on @@ -76,8 +78,6 @@ #[crate_name] //~^ ERROR malformed //~| WARN crate-level attribute should be an inner attribute -#[doc] -//~^ ERROR #[target_feature] //~^ ERROR malformed #[export_stable = 1] diff --git a/tests/ui/attributes/malformed-attrs.stderr b/tests/ui/attributes/malformed-attrs.stderr index 213e017a6be4d..72e7776e09209 100644 --- a/tests/ui/attributes/malformed-attrs.stderr +++ b/tests/ui/attributes/malformed-attrs.stderr @@ -191,7 +191,7 @@ LL | #[deprecated = 5] | expected a string literal here error[E0539]: malformed `rustc_macro_transparency` attribute input - --> $DIR/malformed-attrs.rs:43:3 + --> $DIR/malformed-attrs.rs:45:3 | LL | #[rustc_macro_transparency] | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -206,7 +206,7 @@ LL | #[rustc_macro_transparency = "transparent"] | +++++++++++++++ error: the `rustc_macro_transparency` attribute cannot be used on functions - --> $DIR/malformed-attrs.rs:43:3 + --> $DIR/malformed-attrs.rs:45:3 | LL | #[rustc_macro_transparency] | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -214,7 +214,7 @@ LL | #[rustc_macro_transparency] = help: the `rustc_macro_transparency` attribute can only be applied to macro defs error[E0539]: malformed `repr` attribute input - --> $DIR/malformed-attrs.rs:46:3 + --> $DIR/malformed-attrs.rs:48:3 | LL | #[repr] | ^^^^ expected this to be a list @@ -222,7 +222,7 @@ LL | #[repr] = note: for more information, visit error[E0565]: malformed `rustc_as_ptr` attribute input - --> $DIR/malformed-attrs.rs:48:3 + --> $DIR/malformed-attrs.rs:50:3 | LL | #[rustc_as_ptr = 5] | ^^^^^^^^^^^^^--- @@ -236,7 +236,7 @@ LL + #[rustc_as_ptr] | error[E0539]: malformed `rustc_align` attribute input - --> $DIR/malformed-attrs.rs:53:3 + --> $DIR/malformed-attrs.rs:55:3 | LL | #[rustc_align] | ^^^^^^^^^^^ expected this to be a list @@ -247,7 +247,7 @@ LL | #[rustc_align()] | ++++++++++++++++++++++ error[E0539]: malformed `optimize` attribute input - --> $DIR/malformed-attrs.rs:55:3 + --> $DIR/malformed-attrs.rs:57:3 | LL | #[optimize] | ^^^^^^^^ expected this to be a list @@ -262,7 +262,7 @@ LL | #[optimize(speed)] | +++++++ error[E0805]: malformed `optimize` attribute input - --> $DIR/malformed-attrs.rs:57:3 + --> $DIR/malformed-attrs.rs:59:3 | LL | #[optimize(none, none)] | ^^^^^^^^------------ @@ -282,7 +282,7 @@ LL + #[optimize(speed)] | error[E0805]: malformed `optimize` attribute input - --> $DIR/malformed-attrs.rs:59:3 + --> $DIR/malformed-attrs.rs:61:3 | LL | #[optimize(none, speed)] | ^^^^^^^^------------- @@ -302,7 +302,7 @@ LL + #[optimize(speed)] | error[E0565]: malformed `cold` attribute input - --> $DIR/malformed-attrs.rs:61:3 + --> $DIR/malformed-attrs.rs:63:3 | LL | #[cold = 1] | ^^^^^--- @@ -316,7 +316,7 @@ LL + #[cold] | error[E0539]: malformed `must_use` attribute input - --> $DIR/malformed-attrs.rs:63:3 + --> $DIR/malformed-attrs.rs:65:3 | LL | #[must_use()] | ^^^^^^^^-- @@ -334,7 +334,7 @@ LL + #[must_use = "reason"] | error[E0565]: malformed `no_mangle` attribute input - --> $DIR/malformed-attrs.rs:65:3 + --> $DIR/malformed-attrs.rs:67:3 | LL | #[no_mangle = 1] | ^^^^^^^^^^--- @@ -348,7 +348,7 @@ LL + #[no_mangle] | error[E0565]: malformed `naked` attribute input - --> $DIR/malformed-attrs.rs:67:3 + --> $DIR/malformed-attrs.rs:69:3 | LL | #[unsafe(naked())] | ^^^^^^^^^^^^--^ @@ -362,7 +362,7 @@ LL + #[unsafe(naked)] | error[E0565]: malformed `track_caller` attribute input - --> $DIR/malformed-attrs.rs:69:3 + --> $DIR/malformed-attrs.rs:71:3 | LL | #[track_caller()] | ^^^^^^^^^^^^-- @@ -376,7 +376,7 @@ LL + #[track_caller] | error[E0539]: malformed `export_name` attribute input - --> $DIR/malformed-attrs.rs:71:3 + --> $DIR/malformed-attrs.rs:73:3 | LL | #[export_name()] | ^^^^^^^^^^^^^ @@ -388,7 +388,7 @@ LL + #[export_name = "name"] | error[E0805]: malformed `used` attribute input - --> $DIR/malformed-attrs.rs:73:3 + --> $DIR/malformed-attrs.rs:75:3 | LL | #[used()] | ^^^^-- @@ -406,7 +406,7 @@ LL | #[used(linker)] | ++++++ error: the `used` attribute cannot be used on functions - --> $DIR/malformed-attrs.rs:73:3 + --> $DIR/malformed-attrs.rs:75:3 | LL | #[used()] | ^^^^ @@ -414,7 +414,7 @@ LL | #[used()] = help: the `used` attribute can only be applied to statics error[E0539]: malformed `crate_name` attribute input - --> $DIR/malformed-attrs.rs:76:3 + --> $DIR/malformed-attrs.rs:78:3 | LL | #[crate_name] | ^^^^^^^^^^ @@ -852,7 +852,7 @@ LL | | #[coroutine = 63] || {} LL | | } | |_- not a `const fn` -error: valid forms for the attribute are `doc = "string"`, `doc(alias)`, `doc(attribute)`, `doc(auto_cfg)`, `doc(cfg)`, `doc(fake_variadic)`, `doc(hidden)`, `doc(html_favicon_url)`, `doc(html_logo_url)`, `doc(html_no_source)`, `doc(html_playground_url)`, `doc(html_root_url)`, `doc(include)`, `doc(inline)`, `doc(issue_tracker_base_url)`, `doc(keyword)`, `doc(masked)`, `doc(no_default_passes)`, `doc(no_inline)`, `doc(notable_trait)`, `doc(passes)`, `doc(plugins)`, `doc(rust_logo)`, `doc(search_unbox)`, `doc(spotlight)`, and `doc(test)` +error: valid forms for the attribute are `doc = "doc comment"`, `doc(alias)`, `doc(auto_cfg)`, `doc(cfg)`, `doc(hidden)`, `doc(html_favicon_url)`, `doc(html_logo_url)`, `doc(html_no_source)`, `doc(html_playground_url)`, `doc(html_root_url)`, `doc(inline)`, `doc(issue_tracker_base_url)`, `doc(masked)`, `doc(no_inline)`, `doc(notable_trait)`, and `doc(test)` --> $DIR/malformed-attrs.rs:41:3 | LL | #[doc] @@ -864,8 +864,14 @@ note: the lint level is defined here LL | #![deny(invalid_doc_attributes)] | ^^^^^^^^^^^^^^^^^^^^^^ +error: valid forms for the attribute are `doc = "doc comment"`, `doc(alias)`, `doc(auto_cfg)`, `doc(cfg)`, `doc(hidden)`, `doc(html_favicon_url)`, `doc(html_logo_url)`, `doc(html_no_source)`, `doc(html_playground_url)`, `doc(html_root_url)`, `doc(inline)`, `doc(issue_tracker_base_url)`, `doc(masked)`, `doc(no_inline)`, `doc(notable_trait)`, and `doc(test)` + --> $DIR/malformed-attrs.rs:43:3 + | +LL | #[doc()] + | ^^^^^ + error: valid forms for the attribute are `inline`, `inline(always)`, and `inline(never)` - --> $DIR/malformed-attrs.rs:50:3 + --> $DIR/malformed-attrs.rs:52:3 | LL | #[inline = 5] | ^^^^^^^^^^ @@ -875,7 +881,7 @@ LL | #[inline = 5] = note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]` - --> $DIR/malformed-attrs.rs:76:1 + --> $DIR/malformed-attrs.rs:78:1 | LL | #[crate_name] | ^^^^^^^^^^^^^ @@ -890,12 +896,6 @@ LL | | } | |_^ = note: requested on the command line with `-W unused-attributes` -error: valid forms for the attribute are `doc = "string"`, `doc(alias)`, `doc(attribute)`, `doc(auto_cfg)`, `doc(cfg)`, `doc(fake_variadic)`, `doc(hidden)`, `doc(html_favicon_url)`, `doc(html_logo_url)`, `doc(html_no_source)`, `doc(html_playground_url)`, `doc(html_root_url)`, `doc(include)`, `doc(inline)`, `doc(issue_tracker_base_url)`, `doc(keyword)`, `doc(masked)`, `doc(no_default_passes)`, `doc(no_inline)`, `doc(notable_trait)`, `doc(passes)`, `doc(plugins)`, `doc(rust_logo)`, `doc(search_unbox)`, `doc(spotlight)`, and `doc(test)` - --> $DIR/malformed-attrs.rs:79:3 - | -LL | #[doc] - | ^^^ - warning: the `link` attribute cannot be used on functions --> $DIR/malformed-attrs.rs:85:3 | @@ -990,7 +990,7 @@ Some errors have detailed explanations: E0308, E0463, E0539, E0565, E0658, E0805 For more information about an error, try `rustc --explain E0308`. Future incompatibility report: Future breakage diagnostic: error: valid forms for the attribute are `inline`, `inline(always)`, and `inline(never)` - --> $DIR/malformed-attrs.rs:50:3 + --> $DIR/malformed-attrs.rs:52:3 | LL | #[inline = 5] | ^^^^^^^^^^ diff --git a/tests/ui/const-generics/gca/const-pattern-field-type-mismatch-162394.rs b/tests/ui/const-generics/gca/const-pattern-field-type-mismatch-162394.rs index 9557c9da80702..181693c365255 100644 --- a/tests/ui/const-generics/gca/const-pattern-field-type-mismatch-162394.rs +++ b/tests/ui/const-generics/gca/const-pattern-field-type-mismatch-162394.rs @@ -2,6 +2,7 @@ #![allow(incomplete_features)] #![feature(macroless_generic_const_args)] +#![feature(macroless_const_item_generic_const_args)] #![feature(generic_const_args, min_generic_const_args)] #![feature(min_adt_const_params)] diff --git a/tests/ui/const-generics/gca/const-pattern-field-type-mismatch-162394.stderr b/tests/ui/const-generics/gca/const-pattern-field-type-mismatch-162394.stderr index afa00eaeed7e7..9dd229cc46a34 100644 --- a/tests/ui/const-generics/gca/const-pattern-field-type-mismatch-162394.stderr +++ b/tests/ui/const-generics/gca/const-pattern-field-type-mismatch-162394.stderr @@ -1,5 +1,5 @@ error: the constant `"foo"` is not of type `()` - --> $DIR/const-pattern-field-type-mismatch-162394.rs:16:5 + --> $DIR/const-pattern-field-type-mismatch-162394.rs:17:5 | LL | const A2: Foo = Self::FooA("foo"); | ^^^^^^^^^^^^^ expected `()`, found `&'static str` diff --git a/tests/ui/const-generics/gca/non-type-equality-ok.rs b/tests/ui/const-generics/gca/non-type-equality-ok.rs index 45dcef1f2dc00..ae7c069ea55f5 100644 --- a/tests/ui/const-generics/gca/non-type-equality-ok.rs +++ b/tests/ui/const-generics/gca/non-type-equality-ok.rs @@ -4,6 +4,7 @@ #![feature( min_generic_const_args, macroless_generic_const_args, + macroless_const_item_generic_const_args, generic_const_args, generic_const_items )] diff --git a/tests/ui/const-generics/mgca/bad-direct-const-arg.rs b/tests/ui/const-generics/mgca/bad-direct-const-arg.rs index 451806ca6e1db..59fdccf29b7b5 100644 --- a/tests/ui/const-generics/mgca/bad-direct-const-arg.rs +++ b/tests/ui/const-generics/mgca/bad-direct-const-arg.rs @@ -1,8 +1,15 @@ -//! Simple error message test, nothing special here +//@ edition: 2024 + +//! Reject direct const arguments in value/type positions without unrelated brace suggestions. #![feature(min_generic_const_args)] +#![deny(unused_braces)] fn main(x: core::direct_const_arg!(2)) { //~^ ERROR expected type, found `direct_const_arg!()` constant let _ = core::direct_const_arg!(2); //~^ ERROR expected expression, found `direct_const_arg!()` constant + consume({ core::direct_const_arg!(2) }); + //~^ ERROR expected expression, found `direct_const_arg!()` constant } + +fn consume(_: usize) {} diff --git a/tests/ui/const-generics/mgca/bad-direct-const-arg.stderr b/tests/ui/const-generics/mgca/bad-direct-const-arg.stderr index b77791ad5b3ee..d54a2c4400ea7 100644 --- a/tests/ui/const-generics/mgca/bad-direct-const-arg.stderr +++ b/tests/ui/const-generics/mgca/bad-direct-const-arg.stderr @@ -1,14 +1,20 @@ error: expected expression, found `direct_const_arg!()` constant - --> $DIR/bad-direct-const-arg.rs:6:13 + --> $DIR/bad-direct-const-arg.rs:9:13 | LL | let _ = core::direct_const_arg!(2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: expected expression, found `direct_const_arg!()` constant + --> $DIR/bad-direct-const-arg.rs:11:15 + | +LL | consume({ core::direct_const_arg!(2) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + error: expected type, found `direct_const_arg!()` constant - --> $DIR/bad-direct-const-arg.rs:4:12 + --> $DIR/bad-direct-const-arg.rs:7:12 | LL | fn main(x: core::direct_const_arg!(2)) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/derives/deriving-all-codegen.stdout b/tests/ui/derives/deriving-all-codegen.stdout index 320c1b5861162..54b1976207236 100644 --- a/tests/ui/derives/deriving-all-codegen.stdout +++ b/tests/ui/derives/deriving-all-codegen.stdout @@ -46,7 +46,7 @@ impl ::core::fmt::Debug for Empty { #[automatically_derived] impl ::core::default::Default for Empty { #[inline] - fn default() -> Empty { Empty {} } + fn default() -> Empty { Empty } } #[automatically_derived] impl ::core::hash::Hash for Empty { diff --git a/tests/ui/feature-gates/feature-gate-macroless_const_item_generic_const_args.macroful.stderr b/tests/ui/feature-gates/feature-gate-macroless_const_item_generic_const_args.macroful.stderr new file mode 100644 index 0000000000000..d49f65acd5a0e --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-macroless_const_item_generic_const_args.macroful.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/feature-gate-macroless_const_item_generic_const_args.rs:24:11 + | +LL | let a: [(); <() as Trait>::ASSOC::] + | ------------------------------- expected due to this +LL | = [(); N]; + | ^^^^^^^ expected an array with a size of <() as Trait>::ASSOC::, found one with a size of N + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/feature-gates/feature-gate-macroless_const_item_generic_const_args.rs b/tests/ui/feature-gates/feature-gate-macroless_const_item_generic_const_args.rs new file mode 100644 index 0000000000000..a967dffcd39af --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-macroless_const_item_generic_const_args.rs @@ -0,0 +1,28 @@ +//@ revisions: macroless macroful +//@[macroless] check-pass +//@ compile-flags: -Znext-solver + +#![feature( + min_generic_const_args, + generic_const_args, + macroless_generic_const_args, + generic_const_items, +)] + +#![cfg_attr(macroless, feature(macroless_const_item_generic_const_args))] + +trait Trait { + const ASSOC: usize; +} + +impl Trait for () { + const ASSOC: usize = N; +} + +fn foo() { + let a: [(); <() as Trait>::ASSOC::] + = [(); N]; + //[macroful]~^ ERROR: mismatched types +} + +fn main() {} diff --git a/tests/ui/lint/unused_braces-issue-154247.fixed b/tests/ui/lint/unused_braces-issue-154247.fixed new file mode 100644 index 0000000000000..08c8999611eb9 --- /dev/null +++ b/tests/ui/lint/unused_braces-issue-154247.fixed @@ -0,0 +1,167 @@ +//@ edition: 2024 +//@ check-pass +//@ run-rustfix + +#![feature(move_expr)] +#![warn(unused_braces)] + +use std::sync::Mutex; + +fn consume(lock: &Mutex>, _value: usize) { + let _guard = lock.lock().unwrap(); +} + +fn consume_int(_: T) {} + +fn make_int() -> usize { + 7 +} + +fn static_int_ref() -> &'static usize { + &7 +} + +struct Point { + _x: usize, +} + +struct Pair { + _x: usize, + _y: usize, +} + +fn make_pair() -> Pair { + Pair { _x: 1, _y: 2 } +} + +macro_rules! make_int_macro { + () => { + make_int() + }; +} + +struct Lockable(Mutex>); + +impl Lockable { + fn update(&self, _value: usize) { + let _guard = self.0.lock().unwrap(); + } + + fn run(&self) { + // These blocks shorten the lifetime of the temporary `MutexGuard`. + consume(&self.0, { self.0.lock().unwrap().len() }); + self.update({ self.0.lock().unwrap().len() }); + consume_int({ [self.0.lock().unwrap().len()] }); + } +} + +fn main() { + let x = 7; + + consume_int(7); + //~^ WARN unnecessary braces + + consume_int(x); + //~^ WARN unnecessary braces + + consume_int(x as usize); + //~^ WARN unnecessary braces + + consume_int((x, 7)); + //~^ WARN unnecessary braces + + consume_int([x, 7]); + //~^ WARN unnecessary braces + + consume_int(!false); + //~^ WARN unnecessary braces + + consume_int(x + 1); + //~^ WARN unnecessary braces + + consume_int([x, 7][0]); + //~^ WARN unnecessary braces + + consume_int(0..x); + //~^ WARN unnecessary braces + + consume_int(const { 7 }); + //~^ WARN unnecessary braces + + consume_int(if x > 0 { x } else { 0 }); + //~^ WARN unnecessary braces + + consume_int(while false {}); + //~^ WARN unnecessary braces + + consume_int(for _ in 0..0 {}); + //~^ WARN unnecessary braces + + consume_int(loop { break x; }); + //~^ WARN unnecessary braces + + consume_int(match x { 0 => 1, _ => x }); + //~^ WARN unnecessary braces + + consume_int(x); + //~^ WARN unnecessary braces + //~| WARN unnecessary braces + + consume_int(|| x); + //~^ WARN unnecessary braces + + let mut y = x; + + consume_int(y += 1); + //~^ WARN unnecessary braces + + consume_int(y); + + consume_int(y = x); + //~^ WARN unnecessary braces + + consume_int(y); + + consume_int(Point { _x: x }); + //~^ WARN unnecessary braces + + consume_int([x; 2]); + //~^ WARN unnecessary braces + + consume_int(&x); + //~^ WARN unnecessary braces + + let move_expr_closure = || { + consume_int(move(x)); + //~^ WARN unnecessary braces + + consume_int({ move(make_int()) }); + }; + move_expr_closure(); + + Lockable(Mutex::new(vec![1])).update(7); + //~^ WARN unnecessary braces + + Lockable(Mutex::new(vec![1])).update(x as usize); + //~^ WARN unnecessary braces + + Lockable(Mutex::new(vec![1])).run(); + + // These blocks contain calls, borrows, macros, or projections where removing + // the argument block may extend temporaries in Rust 2024. + consume_int({ make_int() }); + consume_int({ make_int() + 1 }); + consume_int({ String::from("abc").len() }); + consume_int({ [make_int(), x] }); + consume_int({ [x, make_int()][0] }); + consume_int({ 0..make_int() }); + consume_int({ Point { _x: make_int() } }); + consume_int({ Pair { _x: x, ..make_pair() } }); + consume_int({ [make_int(); 2] }); + consume_int({ make_int_macro!() }); + consume_int({ format_args!("value") }); + consume_int({ &*static_int_ref() }); + + let point = Point { _x: x }; + consume_int({ point._x }); +} diff --git a/tests/ui/lint/unused_braces-issue-154247.rs b/tests/ui/lint/unused_braces-issue-154247.rs new file mode 100644 index 0000000000000..6d2f28c4d5a2b --- /dev/null +++ b/tests/ui/lint/unused_braces-issue-154247.rs @@ -0,0 +1,167 @@ +//@ edition: 2024 +//@ check-pass +//@ run-rustfix + +#![feature(move_expr)] +#![warn(unused_braces)] + +use std::sync::Mutex; + +fn consume(lock: &Mutex>, _value: usize) { + let _guard = lock.lock().unwrap(); +} + +fn consume_int(_: T) {} + +fn make_int() -> usize { + 7 +} + +fn static_int_ref() -> &'static usize { + &7 +} + +struct Point { + _x: usize, +} + +struct Pair { + _x: usize, + _y: usize, +} + +fn make_pair() -> Pair { + Pair { _x: 1, _y: 2 } +} + +macro_rules! make_int_macro { + () => { + make_int() + }; +} + +struct Lockable(Mutex>); + +impl Lockable { + fn update(&self, _value: usize) { + let _guard = self.0.lock().unwrap(); + } + + fn run(&self) { + // These blocks shorten the lifetime of the temporary `MutexGuard`. + consume(&self.0, { self.0.lock().unwrap().len() }); + self.update({ self.0.lock().unwrap().len() }); + consume_int({ [self.0.lock().unwrap().len()] }); + } +} + +fn main() { + let x = 7; + + consume_int({ 7 }); + //~^ WARN unnecessary braces + + consume_int({ x }); + //~^ WARN unnecessary braces + + consume_int({ x as usize }); + //~^ WARN unnecessary braces + + consume_int({ (x, 7) }); + //~^ WARN unnecessary braces + + consume_int({ [x, 7] }); + //~^ WARN unnecessary braces + + consume_int({ !false }); + //~^ WARN unnecessary braces + + consume_int({ x + 1 }); + //~^ WARN unnecessary braces + + consume_int({ [x, 7][0] }); + //~^ WARN unnecessary braces + + consume_int({ 0..x }); + //~^ WARN unnecessary braces + + consume_int({ const { 7 } }); + //~^ WARN unnecessary braces + + consume_int({ if x > 0 { x } else { 0 } }); + //~^ WARN unnecessary braces + + consume_int({ while false {} }); + //~^ WARN unnecessary braces + + consume_int({ for _ in 0..0 {} }); + //~^ WARN unnecessary braces + + consume_int({ loop { break x; } }); + //~^ WARN unnecessary braces + + consume_int({ match x { 0 => 1, _ => x } }); + //~^ WARN unnecessary braces + + consume_int({ { x } }); + //~^ WARN unnecessary braces + //~| WARN unnecessary braces + + consume_int({ || x }); + //~^ WARN unnecessary braces + + let mut y = x; + + consume_int({ y += 1 }); + //~^ WARN unnecessary braces + + consume_int(y); + + consume_int({ y = x }); + //~^ WARN unnecessary braces + + consume_int(y); + + consume_int({ Point { _x: x } }); + //~^ WARN unnecessary braces + + consume_int({ [x; 2] }); + //~^ WARN unnecessary braces + + consume_int({ &x }); + //~^ WARN unnecessary braces + + let move_expr_closure = || { + consume_int({ move(x) }); + //~^ WARN unnecessary braces + + consume_int({ move(make_int()) }); + }; + move_expr_closure(); + + Lockable(Mutex::new(vec![1])).update({ 7 }); + //~^ WARN unnecessary braces + + Lockable(Mutex::new(vec![1])).update({ x as usize }); + //~^ WARN unnecessary braces + + Lockable(Mutex::new(vec![1])).run(); + + // These blocks contain calls, borrows, macros, or projections where removing + // the argument block may extend temporaries in Rust 2024. + consume_int({ make_int() }); + consume_int({ make_int() + 1 }); + consume_int({ String::from("abc").len() }); + consume_int({ [make_int(), x] }); + consume_int({ [x, make_int()][0] }); + consume_int({ 0..make_int() }); + consume_int({ Point { _x: make_int() } }); + consume_int({ Pair { _x: x, ..make_pair() } }); + consume_int({ [make_int(); 2] }); + consume_int({ make_int_macro!() }); + consume_int({ format_args!("value") }); + consume_int({ &*static_int_ref() }); + + let point = Point { _x: x }; + consume_int({ point._x }); +} diff --git a/tests/ui/lint/unused_braces-issue-154247.stderr b/tests/ui/lint/unused_braces-issue-154247.stderr new file mode 100644 index 0000000000000..5d5fd1c95513a --- /dev/null +++ b/tests/ui/lint/unused_braces-issue-154247.stderr @@ -0,0 +1,319 @@ +warning: unnecessary braces around function argument + --> $DIR/unused_braces-issue-154247.rs:61:17 + | +LL | consume_int({ 7 }); + | ^^ ^^ + | +note: the lint level is defined here + --> $DIR/unused_braces-issue-154247.rs:6:9 + | +LL | #![warn(unused_braces)] + | ^^^^^^^^^^^^^ +help: remove these braces + | +LL - consume_int({ 7 }); +LL + consume_int(7); + | + +warning: unnecessary braces around function argument + --> $DIR/unused_braces-issue-154247.rs:64:17 + | +LL | consume_int({ x }); + | ^^ ^^ + | +help: remove these braces + | +LL - consume_int({ x }); +LL + consume_int(x); + | + +warning: unnecessary braces around function argument + --> $DIR/unused_braces-issue-154247.rs:67:17 + | +LL | consume_int({ x as usize }); + | ^^ ^^ + | +help: remove these braces + | +LL - consume_int({ x as usize }); +LL + consume_int(x as usize); + | + +warning: unnecessary braces around function argument + --> $DIR/unused_braces-issue-154247.rs:70:17 + | +LL | consume_int({ (x, 7) }); + | ^^ ^^ + | +help: remove these braces + | +LL - consume_int({ (x, 7) }); +LL + consume_int((x, 7)); + | + +warning: unnecessary braces around function argument + --> $DIR/unused_braces-issue-154247.rs:73:17 + | +LL | consume_int({ [x, 7] }); + | ^^ ^^ + | +help: remove these braces + | +LL - consume_int({ [x, 7] }); +LL + consume_int([x, 7]); + | + +warning: unnecessary braces around function argument + --> $DIR/unused_braces-issue-154247.rs:76:17 + | +LL | consume_int({ !false }); + | ^^ ^^ + | +help: remove these braces + | +LL - consume_int({ !false }); +LL + consume_int(!false); + | + +warning: unnecessary braces around function argument + --> $DIR/unused_braces-issue-154247.rs:79:17 + | +LL | consume_int({ x + 1 }); + | ^^ ^^ + | +help: remove these braces + | +LL - consume_int({ x + 1 }); +LL + consume_int(x + 1); + | + +warning: unnecessary braces around function argument + --> $DIR/unused_braces-issue-154247.rs:82:17 + | +LL | consume_int({ [x, 7][0] }); + | ^^ ^^ + | +help: remove these braces + | +LL - consume_int({ [x, 7][0] }); +LL + consume_int([x, 7][0]); + | + +warning: unnecessary braces around function argument + --> $DIR/unused_braces-issue-154247.rs:85:17 + | +LL | consume_int({ 0..x }); + | ^^ ^^ + | +help: remove these braces + | +LL - consume_int({ 0..x }); +LL + consume_int(0..x); + | + +warning: unnecessary braces around function argument + --> $DIR/unused_braces-issue-154247.rs:88:17 + | +LL | consume_int({ const { 7 } }); + | ^^ ^^ + | +help: remove these braces + | +LL - consume_int({ const { 7 } }); +LL + consume_int(const { 7 }); + | + +warning: unnecessary braces around function argument + --> $DIR/unused_braces-issue-154247.rs:91:17 + | +LL | consume_int({ if x > 0 { x } else { 0 } }); + | ^^ ^^ + | +help: remove these braces + | +LL - consume_int({ if x > 0 { x } else { 0 } }); +LL + consume_int(if x > 0 { x } else { 0 }); + | + +warning: unnecessary braces around function argument + --> $DIR/unused_braces-issue-154247.rs:94:17 + | +LL | consume_int({ while false {} }); + | ^^ ^^ + | +help: remove these braces + | +LL - consume_int({ while false {} }); +LL + consume_int(while false {}); + | + +warning: unnecessary braces around function argument + --> $DIR/unused_braces-issue-154247.rs:97:17 + | +LL | consume_int({ for _ in 0..0 {} }); + | ^^ ^^ + | +help: remove these braces + | +LL - consume_int({ for _ in 0..0 {} }); +LL + consume_int(for _ in 0..0 {}); + | + +warning: unnecessary braces around function argument + --> $DIR/unused_braces-issue-154247.rs:100:17 + | +LL | consume_int({ loop { break x; } }); + | ^^ ^^ + | +help: remove these braces + | +LL - consume_int({ loop { break x; } }); +LL + consume_int(loop { break x; }); + | + +warning: unnecessary braces around function argument + --> $DIR/unused_braces-issue-154247.rs:103:17 + | +LL | consume_int({ match x { 0 => 1, _ => x } }); + | ^^ ^^ + | +help: remove these braces + | +LL - consume_int({ match x { 0 => 1, _ => x } }); +LL + consume_int(match x { 0 => 1, _ => x }); + | + +warning: unnecessary braces around function argument + --> $DIR/unused_braces-issue-154247.rs:106:17 + | +LL | consume_int({ { x } }); + | ^^ ^^ + | +help: remove these braces + | +LL - consume_int({ { x } }); +LL + consume_int({ x }); + | + +warning: unnecessary braces around block return value + --> $DIR/unused_braces-issue-154247.rs:106:19 + | +LL | consume_int({ { x } }); + | ^^ ^^ + | +help: remove these braces + | +LL - consume_int({ { x } }); +LL + consume_int({ x }); + | + +warning: unnecessary braces around function argument + --> $DIR/unused_braces-issue-154247.rs:110:17 + | +LL | consume_int({ || x }); + | ^^ ^^ + | +help: remove these braces + | +LL - consume_int({ || x }); +LL + consume_int(|| x); + | + +warning: unnecessary braces around function argument + --> $DIR/unused_braces-issue-154247.rs:115:17 + | +LL | consume_int({ y += 1 }); + | ^^ ^^ + | +help: remove these braces + | +LL - consume_int({ y += 1 }); +LL + consume_int(y += 1); + | + +warning: unnecessary braces around function argument + --> $DIR/unused_braces-issue-154247.rs:120:17 + | +LL | consume_int({ y = x }); + | ^^ ^^ + | +help: remove these braces + | +LL - consume_int({ y = x }); +LL + consume_int(y = x); + | + +warning: unnecessary braces around function argument + --> $DIR/unused_braces-issue-154247.rs:125:17 + | +LL | consume_int({ Point { _x: x } }); + | ^^ ^^ + | +help: remove these braces + | +LL - consume_int({ Point { _x: x } }); +LL + consume_int(Point { _x: x }); + | + +warning: unnecessary braces around function argument + --> $DIR/unused_braces-issue-154247.rs:128:17 + | +LL | consume_int({ [x; 2] }); + | ^^ ^^ + | +help: remove these braces + | +LL - consume_int({ [x; 2] }); +LL + consume_int([x; 2]); + | + +warning: unnecessary braces around function argument + --> $DIR/unused_braces-issue-154247.rs:131:17 + | +LL | consume_int({ &x }); + | ^^ ^^ + | +help: remove these braces + | +LL - consume_int({ &x }); +LL + consume_int(&x); + | + +warning: unnecessary braces around function argument + --> $DIR/unused_braces-issue-154247.rs:135:21 + | +LL | consume_int({ move(x) }); + | ^^ ^^ + | +help: remove these braces + | +LL - consume_int({ move(x) }); +LL + consume_int(move(x)); + | + +warning: unnecessary braces around method argument + --> $DIR/unused_braces-issue-154247.rs:142:42 + | +LL | Lockable(Mutex::new(vec![1])).update({ 7 }); + | ^^ ^^ + | +help: remove these braces + | +LL - Lockable(Mutex::new(vec![1])).update({ 7 }); +LL + Lockable(Mutex::new(vec![1])).update(7); + | + +warning: unnecessary braces around method argument + --> $DIR/unused_braces-issue-154247.rs:145:42 + | +LL | Lockable(Mutex::new(vec![1])).update({ x as usize }); + | ^^ ^^ + | +help: remove these braces + | +LL - Lockable(Mutex::new(vec![1])).update({ x as usize }); +LL + Lockable(Mutex::new(vec![1])).update(x as usize); + | + +warning: 26 warnings emitted + diff --git a/tests/ui/malformed/malformed-regressions.stderr b/tests/ui/malformed/malformed-regressions.stderr index 693b16c610bb2..0dcdee9ccc990 100644 --- a/tests/ui/malformed/malformed-regressions.stderr +++ b/tests/ui/malformed/malformed-regressions.stderr @@ -16,7 +16,7 @@ LL | #[link = ""] | = note: for more information, visit -error: valid forms for the attribute are `doc = "string"`, `doc(alias)`, `doc(attribute)`, `doc(auto_cfg)`, `doc(cfg)`, `doc(fake_variadic)`, `doc(hidden)`, `doc(html_favicon_url)`, `doc(html_logo_url)`, `doc(html_no_source)`, `doc(html_playground_url)`, `doc(html_root_url)`, `doc(include)`, `doc(inline)`, `doc(issue_tracker_base_url)`, `doc(keyword)`, `doc(masked)`, `doc(no_default_passes)`, `doc(no_inline)`, `doc(notable_trait)`, `doc(passes)`, `doc(plugins)`, `doc(rust_logo)`, `doc(search_unbox)`, `doc(spotlight)`, and `doc(test)` +error: valid forms for the attribute are `doc = "doc comment"`, `doc(alias)`, `doc(auto_cfg)`, `doc(cfg)`, `doc(hidden)`, `doc(html_favicon_url)`, `doc(html_logo_url)`, `doc(html_no_source)`, `doc(html_playground_url)`, `doc(html_root_url)`, `doc(inline)`, `doc(issue_tracker_base_url)`, `doc(masked)`, `doc(no_inline)`, `doc(notable_trait)`, and `doc(test)` --> $DIR/malformed-regressions.rs:3:3 | LL | #[doc]