From 8bb0a9ac7a55c57a75288704629c7f04773e67c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Mon, 15 Jan 2024 02:24:28 +0100 Subject: [PATCH 1/3] Use and create more host effect helpers --- compiler/rustc_ast_lowering/src/item.rs | 5 ++--- compiler/rustc_hir/src/hir.rs | 14 ++++++++++---- .../rustc_hir_analysis/src/astconv/generics.rs | 9 ++------- compiler/rustc_hir_analysis/src/collect.rs | 2 +- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 7 +------ compiler/rustc_middle/src/ty/context.rs | 2 +- compiler/rustc_middle/src/ty/generics.rs | 2 +- 7 files changed, 18 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index a3ff02f5f6954..b1d65887dc8fb 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -600,9 +600,8 @@ impl<'hir> LoweringContext<'_, 'hir> { self.host_param_id = generics .params .iter() - .find(|param| { - matches!(param.kind, hir::GenericParamKind::Const { is_host_effect: true, .. }) - }) + .rev() + .find(|param| param.is_host_effect()) .map(|param| param.def_id); } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 6b347f7035a3b..d5e86787999e1 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -304,6 +304,10 @@ impl GenericArg<'_> { GenericArg::Type(_) | GenericArg::Const(_) | GenericArg::Infer(_) => true, } } + + pub fn is_desugared_from_effects(&self) -> bool { + matches!(self, GenericArg::Const(ConstArg { is_desugared_from_effects: true, .. })) + } } #[derive(Debug, Clone, Copy, HashStable_Generic)] @@ -381,10 +385,8 @@ impl<'hir> GenericArgs<'hir> { pub fn num_generic_params(&self) -> usize { self.args .iter() - .filter(|arg| match arg { - GenericArg::Lifetime(_) - | GenericArg::Const(ConstArg { is_desugared_from_effects: true, .. }) => false, - _ => true, + .filter(|arg| { + !matches!(arg, GenericArg::Lifetime(_)) && !arg.is_desugared_from_effects() }) .count() } @@ -518,6 +520,10 @@ impl<'hir> GenericParam<'hir> { pub fn is_elided_lifetime(&self) -> bool { matches!(self.kind, GenericParamKind::Lifetime { kind: LifetimeParamKind::Elided }) } + + pub fn is_host_effect(&self) -> bool { + matches!(self.kind, GenericParamKind::Const { is_host_effect: true, .. }) + } } /// Records where the generic parameter originated from. diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs index e2cd4d5f21c76..ecff5b149f955 100644 --- a/compiler/rustc_hir_analysis/src/astconv/generics.rs +++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs @@ -454,13 +454,8 @@ pub(crate) fn check_generic_arg_count( .filter(|param| matches!(param.kind, ty::GenericParamDefKind::Type { synthetic: true, .. })) .count(); let named_type_param_count = param_counts.types - has_self as usize - synth_type_param_count; - let synth_const_param_count = gen_params - .params - .iter() - .filter(|param| { - matches!(param.kind, ty::GenericParamDefKind::Const { is_host_effect: true, .. }) - }) - .count(); + let synth_const_param_count = + gen_params.params.iter().filter(|param| param.is_host_effect()).count(); let named_const_param_count = param_counts.consts - synth_const_param_count; let infer_lifetimes = (gen_pos != GenericArgPosition::Type || infer_args) && !gen_args.has_lifetime_params(); diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index e557f36037b6c..95e63f0662e90 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1350,7 +1350,7 @@ fn impl_trait_ref( let last_segment = path_segments.len() - 1; let mut args = *path_segments[last_segment].args(); let last_arg = args.args.len() - 1; - assert!(matches!(args.args[last_arg], hir::GenericArg::Const(anon_const) if anon_const.is_desugared_from_effects)); + assert!(args.args[last_arg].is_desugared_from_effects()); args.args = &args.args[..args.args.len() - 1]; path_segments[last_segment].args = Some(&args); let path = hir::Path { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index fde3d41faecf0..c5fc68d69d06d 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -269,12 +269,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { ) -> Const<'tcx> { // FIXME ideally this shouldn't use unwrap match param { - Some( - param @ ty::GenericParamDef { - kind: ty::GenericParamDefKind::Const { is_host_effect: true, .. }, - .. - }, - ) => self.var_for_effect(param).as_const().unwrap(), + Some(param) if param.is_host_effect() => self.var_for_effect(param).as_const().unwrap(), Some(param) => self.var_for_def(span, param).as_const().unwrap(), None => self.next_const_var( ty, diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 6807eacb7f177..e6fd857d8f218 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2254,7 +2254,7 @@ impl<'tcx> TyCtxt<'tcx> { hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(hir::Impl { generics, .. }), .. - }) if generics.params.iter().any(|p| matches!(p.kind, hir::GenericParamKind::Const { is_host_effect: true, .. })) + }) if generics.params.iter().rev().any(|param| param.is_host_effect()) ) } diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 4821ae3f08735..cc7846a4c6bf5 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -343,7 +343,7 @@ impl<'tcx> Generics { default.instantiate(tcx, args) == args[param.index as usize] }) // filter out trailing effect params, if we're not in `-Zverbose-internals`. - || (!verbose && matches!(param.kind, GenericParamDefKind::Const { is_host_effect: true, .. })) + || (!verbose && param.is_host_effect()) }) .count(); From 5e2e50ac517c1c2d97ea75477565de7e9d61b849 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Mon, 15 Jan 2024 02:24:03 +0100 Subject: [PATCH 2/3] Clean up code in astconv/generics.rs --- .../src/astconv/generics.rs | 47 ++++++++----------- 1 file changed, 19 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs index ecff5b149f955..3b81c5faa838f 100644 --- a/compiler/rustc_hir_analysis/src/astconv/generics.rs +++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs @@ -199,35 +199,26 @@ pub fn create_args_for_parent_generic_args<'tcx, 'a>( // If we have already computed the generic arguments for parents, // we can use those directly. while let Some(¶m) = params.peek() { - if let Some(&kind) = parent_args.get(param.index as usize) { - args.push(kind); - params.next(); - } else { - break; - } + let Some(&kind) = parent_args.get(param.index as usize) else { break }; + args.push(kind); + params.next(); } // `Self` is handled first, unless it's been handled in `parent_args`. - if has_self { - if let Some(¶m) = params.peek() { - if param.index == 0 { - if let GenericParamDefKind::Type { .. } = param.kind { - args.push( - self_ty - .map(|ty| ty.into()) - .unwrap_or_else(|| ctx.inferred_kind(None, param, true)), - ); - params.next(); - } - } - } + if has_self + && let Some(¶m) = params.peek() + && param.index == 0 + && let GenericParamDefKind::Type { .. } = param.kind + { + args.push( + self_ty.map(|ty| ty.into()).unwrap_or_else(|| ctx.inferred_kind(None, param, true)), + ); + params.next(); } // Check whether this segment takes generic arguments and the user has provided any. - let (generic_args, infer_args) = ctx.args_for_def_id(def_id); - - let args_iter = generic_args.iter().flat_map(|generic_args| generic_args.args.iter()); - let mut args_iter = args_iter.clone().peekable(); + let (hir_args, infer_args) = ctx.args_for_def_id(def_id); + let mut hir_args = hir_args.iter().flat_map(|args| args.args.iter()).peekable(); // If we encounter a type or const when we expect a lifetime, we infer the lifetimes. // If we later encounter a lifetime, we know that the arguments were provided in the @@ -240,7 +231,7 @@ pub fn create_args_for_parent_generic_args<'tcx, 'a>( // provided, matching them with the generic parameters we expect. // Mismatches can occur as a result of elided lifetimes, or for malformed // input. We try to handle both sensibly. - match (args_iter.peek(), params.peek()) { + match (hir_args.peek(), params.peek()) { (Some(&arg), Some(¶m)) => { match (arg, ¶m.kind, arg_count.explicit_late_bound) { ( @@ -280,7 +271,7 @@ pub fn create_args_for_parent_generic_args<'tcx, 'a>( _, ) => { args.push(ctx.provided_kind(param, arg)); - args_iter.next(); + hir_args.next(); params.next(); } ( @@ -299,7 +290,7 @@ pub fn create_args_for_parent_generic_args<'tcx, 'a>( // the presence of explicit late bounds. This is most likely // due to the presence of the explicit bound so we're just going to // ignore it. - args_iter.next(); + hir_args.next(); } (_, _, _) => { // We expected one kind of parameter, but the user provided @@ -325,7 +316,7 @@ pub fn create_args_for_parent_generic_args<'tcx, 'a>( tcx, arg, param, - !args_iter.clone().is_sorted_by_key(|arg| arg.to_ord()), + !hir_args.clone().is_sorted_by_key(|arg| arg.to_ord()), Some(format!( "reorder the arguments: {}: `<{}>`", param_types_present @@ -353,7 +344,7 @@ pub fn create_args_for_parent_generic_args<'tcx, 'a>( // errors. In this case, we're simply going to ignore the argument // and any following arguments. The rest of the parameters will be // inferred. - while args_iter.next().is_some() {} + while hir_args.next().is_some() {} } } } From bfea4919599a923afd01c9ac2031b45185d09988 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Mon, 15 Jan 2024 00:51:14 +0100 Subject: [PATCH 3/3] Introduce const-qualified paths --- compiler/rustc_ast/src/ast.rs | 10 ++ compiler/rustc_ast/src/mut_visit.rs | 2 +- compiler/rustc_ast_lowering/src/item.rs | 31 ++-- compiler/rustc_ast_lowering/src/path.rs | 7 +- compiler/rustc_ast_pretty/src/pprust/state.rs | 3 + .../src/astconv/generics.rs | 133 +++++++++++++++++- .../rustc_hir_analysis/src/astconv/mod.rs | 18 ++- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 9 +- .../rustc_hir_typeck/src/method/confirm.rs | 1 + .../rustc_parse/src/parser/diagnostics.rs | 5 +- compiler/rustc_parse/src/parser/path.rs | 22 +-- compiler/rustc_parse/src/parser/ty.rs | 38 +++-- ...-type-const-bound-usage-0.qualified.stderr | 14 -- .../assoc-type-const-bound-usage-0.rs | 9 +- .../assoc-type-const-bound-usage-1.rs | 9 +- .../const-project.always_const_super.stderr | 14 ++ .../const-project.maybe_const_super.stderr | 14 ++ .../const-project.never_const_super.stderr | 14 ++ .../effects/const-project.rs | 26 ++++ .../effects/minicore.rs | 5 +- .../effects/project.always-const-super.stderr | 63 +++++++++ .../effects/project.always_const_super.stderr | 63 +++++++++ .../effects/project.never-const-super.stderr | 63 +++++++++ ...tderr => project.never_const_super.stderr} | 38 +++-- .../effects/project.rs | 31 +++- .../feature-gate.gated.stderr | 2 +- .../rfc-2632-const-trait-impl/feature-gate.rs | 9 +- .../feature-gate.stock.stderr | 24 +++- 28 files changed, 559 insertions(+), 118 deletions(-) delete mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.qualified.stderr create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-project.always_const_super.stderr create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-project.maybe_const_super.stderr create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-project.never_const_super.stderr create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-project.rs create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.always-const-super.stderr create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.always_const_super.stderr create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.never-const-super.stderr rename tests/ui/rfcs/rfc-2632-const-trait-impl/effects/{project.stderr => project.never_const_super.stderr} (56%) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 21077c312bdc8..7bfd50afe6ed9 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1574,6 +1574,16 @@ impl GenBlockKind { pub struct QSelf { pub ty: P, + /// The constness of the trait (under feature `const_trait_impl`). + /// + /// * `::AssocTy`: `BoundConstness::Never` + /// * `::AssocTy`: `BoundConstness::Always` + /// * `::AssocTy`: `BoundConstness::Maybe` + // FIXME(effects): This is the most convenient place to put this information but + // it doesn't make much sense from a conceptual viewpoint since it doesn't have + // much to do with the self type. + pub constness: BoundConstness, + /// The span of `a::b::Trait` in a path like ` as /// a::b::Trait>::AssociatedItem`; in the case where `position == /// 0`, this is an empty span. diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 450555d0cb56d..eb69c0baf16a8 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -559,7 +559,7 @@ pub fn noop_visit_path(Path { segments, span, tokens }: &mut Path pub fn noop_visit_qself(qself: &mut Option>, vis: &mut T) { visit_opt(qself, |qself| { - let QSelf { ty, path_span, position: _ } = &mut **qself; + let QSelf { ty, constness: _, path_span, position: _ } = &mut **qself; vis.visit_ty(ty); vis.visit_span(path_span); }) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index b1d65887dc8fb..420abd6b6b2f4 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -200,36 +200,35 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ItemKind::Const(ty, generics, body_id) } ItemKind::Fn(box Fn { - sig: FnSig { decl, header, span: fn_sig_span }, + sig: FnSig { decl: ast_decl, header, span: fn_sig_span }, generics, body, .. }) => { self.with_new_scopes(ident.span, |this| { - // Note: we don't need to change the return type from `T` to - // `impl Future` here because lower_body - // only cares about the input argument patterns in the function - // declaration (decl), not the return types. - let coroutine_kind = header.coroutine_kind; - let body_id = this.lower_maybe_coroutine_body( - span, - hir_id, - decl, - coroutine_kind, - body.as_deref(), - ); - + // We lower the generics before we lower the body since the body can bind the host + // effect param via qualified paths of the form `::AssocType`. let itctx = ImplTraitContext::Universal; let (generics, decl) = this.lower_generics(generics, header.constness, id, &itctx, |this| { this.lower_fn_decl( - decl, + ast_decl, id, *fn_sig_span, FnDeclKind::Fn, - coroutine_kind, + header.coroutine_kind, ) }); + // Note: We don't need to change the return type from `T` to `impl Future` + // here because `lower_body` only cares about the input argument patterns in the function + // declaration `decl`, not the return types. + let body_id = this.lower_maybe_coroutine_body( + span, + hir_id, + ast_decl, + header.coroutine_kind, + body.as_deref(), + ); let sig = hir::FnSig { decl, header: this.lower_fn_header(*header), diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index c679ee56fcd8b..fdd7a699a9b1b 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -27,6 +27,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // constness of the impl/bound if this is a trait path constness: Option, ) -> hir::QPath<'hir> { + // FIXME(effects): The name isn't great. + let trait_constness = qself.as_ref().map(|q| q.constness); let qself_position = qself.as_ref().map(|q| q.position); let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx)); @@ -76,8 +78,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { param_mode, parenthesized_generic_args, itctx, - // if this is the last segment, add constness to the trait path - if i == proj_start - 1 { constness } else { None }, + // If this is the last segment, add constness to the trait path. + // FIXME(effects): Is it possible that both constnesses are Some? + if i == proj_start - 1 { constness } else { trait_constness }, ) }, )), diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index f4b424259deef..e762eb62c49f0 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1377,6 +1377,9 @@ impl<'a> State<'a> { if qself.position > 0 { self.space(); self.word_space("as"); + if qself.constness != ast::BoundConstness::Never { + self.word_space(qself.constness.as_str()); + } let depth = path.segments.len() - qself.position; self.print_path(path, false, depth); } diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs index 3b81c5faa838f..66192ac386b69 100644 --- a/compiler/rustc_hir_analysis/src/astconv/generics.rs +++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs @@ -12,9 +12,11 @@ use rustc_hir::def_id::DefId; use rustc_hir::GenericArg; use rustc_middle::ty::{ self, GenericArgsRef, GenericParamDef, GenericParamDefKind, IsSuggestable, Ty, TyCtxt, + TypeVisitableExt, }; use rustc_session::lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS; use rustc_span::{symbol::kw, Span}; +use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use smallvec::SmallVec; /// Report an error that a generic argument did not match the generic parameter that was @@ -211,14 +213,39 @@ pub fn create_args_for_parent_generic_args<'tcx, 'a>( && let GenericParamDefKind::Type { .. } = param.kind { args.push( - self_ty.map(|ty| ty.into()).unwrap_or_else(|| ctx.inferred_kind(None, param, true)), + self_ty + .map(|ty| ty.into()) + .unwrap_or_else(|| ctx.inferred_kind(None, None, param, true)), ); params.next(); } // Check whether this segment takes generic arguments and the user has provided any. let (hir_args, infer_args) = ctx.args_for_def_id(def_id); - let mut hir_args = hir_args.iter().flat_map(|args| args.args.iter()).peekable(); + let hir_args = hir_args.iter().flat_map(|args| args.args.iter()); + + let host_effect = defs.host_effect_index.map(|index| { + let arg = hir_args + .clone() + .rev() + .find_map(|arg| match arg { + hir::GenericArg::Const(arg) if arg.is_desugared_from_effects => { + let did = arg.value.def_id; + let param = defs.param_at(index, tcx); + // FIXME(fmease): Add comment why. + tcx.feed_anon_const_type(did, tcx.type_of(param.def_id)); + Some(ty::Const::from_anon_const(tcx, did)) + } + _ => None, + }) + // FIXME(effects): Don't hard-code the default of host effect params here. I guess + // we could `tcx.const_param_default(tcx, param.def_id).no_bound_vars().unwrap()` + // instead which isn't perfect either due to the assumption of “no bound vars”. + .unwrap_or(tcx.consts.true_); + (index, arg) + }); + + let mut hir_args = hir_args.peekable(); // If we encounter a type or const when we expect a lifetime, we infer the lifetimes. // If we later encounter a lifetime, we know that the arguments were provided in the @@ -256,7 +283,12 @@ pub fn create_args_for_parent_generic_args<'tcx, 'a>( // Since this is a const impl, we need to insert a host arg at the end of // `PartialEq`'s generics, but this errors since `Rhs` isn't specified. // To work around this, we infer all arguments until we reach the host param. - args.push(ctx.inferred_kind(Some(&args), param, infer_args)); + args.push(ctx.inferred_kind( + Some(&args), + host_effect, + param, + infer_args, + )); params.next(); } (GenericArg::Lifetime(_), GenericParamDefKind::Lifetime, _) @@ -281,7 +313,7 @@ pub fn create_args_for_parent_generic_args<'tcx, 'a>( ) => { // We expected a lifetime argument, but got a type or const // argument. That means we're inferring the lifetimes. - args.push(ctx.inferred_kind(None, param, infer_args)); + args.push(ctx.inferred_kind(None, None, param, infer_args)); force_infer_lt = Some((arg, param)); params.next(); } @@ -377,7 +409,7 @@ pub fn create_args_for_parent_generic_args<'tcx, 'a>( (None, Some(¶m)) => { // If there are fewer arguments than parameters, it means // we're inferring the remaining arguments. - args.push(ctx.inferred_kind(Some(&args), param, infer_args)); + args.push(ctx.inferred_kind(Some(&args), host_effect, param, infer_args)); params.next(); } @@ -656,3 +688,94 @@ pub(crate) fn prohibit_explicit_late_bound_lifetimes( ExplicitLateBound::No } } + +pub trait EarlyBinderExt<'tcx, T> { + fn instantiate_with_host_effect( + self, + tcx: TyCtxt<'tcx>, + args: &[ty::GenericArg<'tcx>], + host_effect: Option<(usize, ty::Const<'tcx>)>, + ) -> T; +} + +impl<'tcx, T: TypeFoldable>> EarlyBinderExt<'tcx, T> for ty::EarlyBinder { + fn instantiate_with_host_effect( + self, + tcx: TyCtxt<'tcx>, + args: &[ty::GenericArg<'tcx>], + host_effect: Option<(usize, ty::Const<'tcx>)>, + ) -> T { + let Some(host_effect) = host_effect else { + return self.instantiate(tcx, args); + }; + let mut folder = ArgFolder { tcx, args, host_effect, depth: ty::INNERMOST }; + self.skip_binder().fold_with(&mut folder) + } +} + +struct ArgFolder<'a, 'tcx> { + tcx: TyCtxt<'tcx>, + args: &'a [ty::GenericArg<'tcx>], + host_effect: (usize, ty::Const<'tcx>), + depth: ty::DebruijnIndex, +} + +// FIXME: Proper panic messages. +impl<'tcx> TypeFolder> for ArgFolder<'_, 'tcx> { + #[inline] + fn interner(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn fold_binder>>( + &mut self, + t: ty::Binder<'tcx, T>, + ) -> ty::Binder<'tcx, T> { + self.depth.shift_in(1); + let t = t.super_fold_with(self); + self.depth.shift_out(1); + t + } + + fn fold_region(&mut self, re: ty::Region<'tcx>) -> ty::Region<'tcx> { + if let ty::ReEarlyParam(param) = *re { + let arg = self.args.get(param.index as usize).map(|arg| arg.unpack()); + let Some(ty::GenericArgKind::Lifetime(re)) = arg else { bug!() }; + ty::fold::shift_vars(self.tcx, re, self.depth.as_u32()) + } else { + re + } + } + + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + if !ty.has_param() { + return ty; + } + if let ty::Param(param) = *ty.kind() { + let arg = self.args.get(param.index as usize).map(|arg| arg.unpack()); + let Some(ty::GenericArgKind::Type(ty)) = arg else { bug!() }; + ty::fold::shift_vars(self.tcx, ty, self.depth.as_u32()) + } else { + ty.super_fold_with(self) + } + } + + fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { + if !ct.has_param() { + return ct; + } + if let ty::ConstKind::Param(param) = ct.kind() { + let (host_effect_index, host_effect_arg) = self.host_effect; + if param.index as usize == host_effect_index { + assert!(self.depth == ty::INNERMOST || !host_effect_arg.has_escaping_bound_vars()); + host_effect_arg + } else { + let arg = self.args.get(param.index as usize).map(|arg| arg.unpack()); + let Some(ty::GenericArgKind::Const(ct)) = arg else { bug!() }; + ty::fold::shift_vars(self.tcx, ct, self.depth.as_u32()) + } + } else { + ct.super_fold_with(self) + } + } +} diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 9f4f1413650f9..931c205ef523f 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -9,6 +9,7 @@ mod lint; mod object_safety; use crate::astconv::errors::prohibit_assoc_ty_binding; +use crate::astconv::generics::EarlyBinderExt; use crate::astconv::generics::{check_generic_arg_count, create_args_for_parent_generic_args}; use crate::bounds::Bounds; use crate::collect::HirPlaceholderCollector; @@ -226,6 +227,7 @@ pub trait CreateSubstsForGenericArgsCtxt<'a, 'tcx> { fn inferred_kind( &mut self, args: Option<&[ty::GenericArg<'tcx>]>, + host_effect: Option<(usize, ty::Const<'tcx>)>, param: &ty::GenericParamDef, infer_args: bool, ) -> ty::GenericArg<'tcx>; @@ -464,9 +466,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { (&GenericParamDefKind::Type { has_default, .. }, GenericArg::Infer(inf)) => { handle_ty_args(has_default, &inf.to_ty()) } - (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => { + (GenericParamDefKind::Const { is_host_effect, .. }, GenericArg::Const(ct)) => { let did = ct.value.def_id; - tcx.feed_anon_const_type(did, tcx.type_of(param.def_id)); + // FIXME(fmease): We add comment why. + if !is_host_effect { + tcx.feed_anon_const_type(did, tcx.type_of(param.def_id)); + } ty::Const::from_anon_const(tcx, did).into() } (&GenericParamDefKind::Const { .. }, hir::GenericArg::Infer(inf)) => { @@ -492,6 +497,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { fn inferred_kind( &mut self, args: Option<&[ty::GenericArg<'tcx>]>, + host_effect: Option<(usize, ty::Const<'tcx>)>, param: &ty::GenericParamDef, infer_args: bool, ) -> ty::GenericArg<'tcx> { @@ -522,7 +528,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Avoid ICE #86756 when type error recovery goes awry. return Ty::new_misc_error(tcx).into(); } - tcx.at(self.span).type_of(param.def_id).instantiate(tcx, args).into() + tcx.at(self.span) + .type_of(param.def_id) + .instantiate_with_host_effect(tcx, args, host_effect) + .into() } else if infer_args { self.astconv.ty_infer(Some(param), self.span).into() } else { @@ -539,10 +548,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { if let Err(guar) = ty.error_reported() { return ty::Const::new_error(tcx, guar, ty).into(); } - // FIXME(effects) see if we should special case effect params here if !infer_args && has_default { tcx.const_param_default(param.def_id) - .instantiate(tcx, args.unwrap()) + .instantiate_with_host_effect(tcx, args.unwrap(), host_effect) .into() } else { if infer_args { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index a4cd9ccc984e1..29c0aed402c62 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -12,7 +12,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_hir::{ExprKind, GenericArg, Node, QPath}; use rustc_hir_analysis::astconv::generics::{ - check_generic_arg_count_for_call, create_args_for_parent_generic_args, + check_generic_arg_count_for_call, create_args_for_parent_generic_args, EarlyBinderExt, }; use rustc_hir_analysis::astconv::{ AstConv, CreateSubstsForGenericArgsCtxt, ExplicitLateBound, GenericArgCountMismatch, @@ -1329,6 +1329,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn inferred_kind( &mut self, args: Option<&[ty::GenericArg<'tcx>]>, + host_effect: Option<(usize, ty::Const<'tcx>)>, param: &ty::GenericParamDef, infer_args: bool, ) -> ty::GenericArg<'tcx> { @@ -1342,7 +1343,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If we have a default, then it doesn't matter that we're not // inferring the type arguments: we provide the default where any // is missing. - tcx.type_of(param.def_id).instantiate(tcx, args.unwrap()).into() + tcx.type_of(param.def_id) + .instantiate_with_host_effect(tcx, args.unwrap(), host_effect) + .into() } else { // If no type arguments were provided, we have to infer them. // This case also occurs as a result of some malformed input, e.g. @@ -1367,7 +1370,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else if !infer_args { return tcx .const_param_default(param.def_id) - .instantiate(tcx, args.unwrap()) + .instantiate_with_host_effect(tcx, args.unwrap(), host_effect) .into(); } } diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index b2ead3cd40b74..f25be835ccd30 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -424,6 +424,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { fn inferred_kind( &mut self, _args: Option<&[ty::GenericArg<'tcx>]>, + _host_effect: Option<(usize, ty::Const<'tcx>)>, param: &ty::GenericParamDef, _infer_args: bool, ) -> ty::GenericArg<'tcx> { diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 720a610fdf518..3f926962c4595 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -1791,7 +1791,10 @@ impl<'a> Parser<'a> { }); let path_span = ty_span.shrink_to_hi(); // Use an empty path since `position == 0`. - Ok(P(T::recovered(Some(P(QSelf { ty, path_span, position: 0 })), path))) + Ok(P(T::recovered( + Some(P(QSelf { ty, constness: ast::BoundConstness::Never, path_span, position: 0 })), + path, + ))) } pub fn maybe_consume_incorrect_semicolon(&mut self, items: &[P]) -> bool { diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index e7cad74b4dd14..f53c9f1d02e5b 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -58,16 +58,18 @@ impl PathStyle { } impl<'a> Parser<'a> { - /// Parses a qualified path. - /// Assumes that the leading `<` has been parsed already. + /// Parses a qualified path. Assumes that the leading `<` has been parsed already. /// - /// `qualified_path = ::path` + /// ```ebnf + /// QualifiedPath = "<" Type BoundConstness Path_type)? ">" "::" Path_$style + /// ``` /// /// # Examples - /// `::default` - /// `::a` - /// `::F::a` (without disambiguator) - /// `::F::a::` (with disambiguator) + /// + /// * `::default` + /// * `::a` + /// * `::F::a` (without disambiguator) + /// * `::F::a::` (with disambiguator) pub(super) fn parse_qpath(&mut self, style: PathStyle) -> PResult<'a, (P, Path)> { let lo = self.prev_token.span; let ty = self.parse_ty()?; @@ -76,12 +78,14 @@ impl<'a> Parser<'a> { // if any (e.g., `U` in the `::*` examples // above). `path_span` has the span of that path, or an empty // span in the case of something like `::Bar`. - let (mut path, path_span); + let (constness, mut path, path_span); if self.eat_keyword(kw::As) { + constness = self.parse_bound_constness()?; let path_lo = self.token.span; path = self.parse_path(PathStyle::Type)?; path_span = path_lo.to(self.prev_token.span); } else { + constness = ast::BoundConstness::Never; path_span = self.token.span.to(self.token.span); path = ast::Path { segments: ThinVec::new(), span: path_span, tokens: None }; } @@ -97,7 +101,7 @@ impl<'a> Parser<'a> { self.expect(&token::ModSep)?; } - let qself = P(QSelf { ty, path_span, position: path.segments.len() }); + let qself = P(QSelf { ty, constness, path_span, position: path.segments.len() }); self.parse_path_segments(&mut path.segments, style, None)?; Ok(( diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index a4fb92c67ac68..099de055e35bc 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -864,21 +864,11 @@ impl<'a> Parser<'a> { /// If no modifiers are present, this does not consume any tokens. /// /// ```ebnf - /// TRAIT_BOUND_MODIFIERS = [["~"] "const"] ["?" | "!"] + /// TRAIT_BOUND_MODIFIERS = BOUND_CONSTNESS BOUND_POLARITY + /// BOUND_POLARITY = ["?" | "!"] /// ``` fn parse_trait_bound_modifiers(&mut self) -> PResult<'a, TraitBoundModifiers> { - let constness = if self.eat(&token::Tilde) { - let tilde = self.prev_token.span; - self.expect_keyword(kw::Const)?; - let span = tilde.to(self.prev_token.span); - self.sess.gated_spans.gate(sym::const_trait_impl, span); - BoundConstness::Maybe(span) - } else if self.eat_keyword(kw::Const) { - self.sess.gated_spans.gate(sym::const_trait_impl, self.prev_token.span); - BoundConstness::Always(self.prev_token.span) - } else { - BoundConstness::Never - }; + let constness = self.parse_bound_constness()?; let polarity = if self.eat(&token::Question) { BoundPolarity::Maybe(self.prev_token.span) @@ -892,6 +882,28 @@ impl<'a> Parser<'a> { Ok(TraitBoundModifiers { constness, polarity }) } + /// Parses the const modifiers that may precede a trait in a bound. + /// + /// If no modifiers are present, this doesn't consume any tokens. + /// + /// ```ebnf + /// BOUND_CONSTNESS = [["~"] "const"] + /// ``` + pub(crate) fn parse_bound_constness(&mut self) -> PResult<'a, BoundConstness> { + Ok(if self.eat(&token::Tilde) { + let tilde = self.prev_token.span; + self.expect_keyword(kw::Const)?; + let span = tilde.to(self.prev_token.span); + self.sess.gated_spans.gate(sym::const_trait_impl, span); + BoundConstness::Maybe(span) + } else if self.eat_keyword(kw::Const) { + self.sess.gated_spans.gate(sym::const_trait_impl, self.prev_token.span); + BoundConstness::Always(self.prev_token.span) + } else { + BoundConstness::Never + }) + } + /// Parses a type bound according to: /// ```ebnf /// TY_BOUND = TY_BOUND_NOPAREN | (TY_BOUND_NOPAREN) diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.qualified.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.qualified.stderr deleted file mode 100644 index 62c8a442ab9bd..0000000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.qualified.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0277]: the trait bound `T: Trait` is not satisfied - --> $DIR/assoc-type-const-bound-usage-0.rs:21:6 - | -LL | ::Assoc::func() - | ^ the trait `Trait` is not implemented for `T` - | -help: consider further restricting this bound - | -LL | const fn qualified() -> i32 { - | +++++++ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.rs index d8573d3af014c..f0547c3c58368 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.rs @@ -1,7 +1,4 @@ -// FIXME(effects): Collapse the revisions into one once we support `::Proj`. -// revisions: unqualified qualified -//[unqualified] check-pass -//[qualified] known-bug: unknown +// check-pass #![feature(const_trait_impl, effects)] @@ -11,14 +8,12 @@ trait Trait { fn func() -> i32; } -#[cfg(unqualified)] const fn unqualified() -> i32 { T::Assoc::func() } -#[cfg(qualified)] const fn qualified() -> i32 { - ::Assoc::func() + ::Assoc::func() } fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-1.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-1.rs index 2190fa337b49f..5a3ad76beb229 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-1.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-1.rs @@ -1,7 +1,4 @@ -// FIXME(effects): Collapse the revisions into one once we support `::Proj`. -// revisions: unqualified qualified -//[unqualified] check-pass -//[qualified] known-bug: unknown +// check-pass #![feature(const_trait_impl, effects, generic_const_exprs)] #![allow(incomplete_features)] @@ -14,13 +11,11 @@ trait Trait { struct Type; -#[cfg(unqualified)] fn unqualified() -> Type<{ T::Assoc::func() }> { Type } -#[cfg(qualified)] -fn qualified() -> Type<{ ::Assoc::func() }> { +fn qualified() -> Type<{ ::Assoc::func() }> { Type } diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-project.always_const_super.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-project.always_const_super.stderr new file mode 100644 index 0000000000000..7b6b7f119ae3e --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-project.always_const_super.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `Self: ~const Uwu` is not satisfied + --> $DIR/const-project.rs:11:33 + | +LL | pub trait Owo::K }> {} + | ^^^^ the trait `~const Uwu` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | pub trait Owo::K }>: ~const Uwu {} + | ++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-project.maybe_const_super.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-project.maybe_const_super.stderr new file mode 100644 index 0000000000000..7b6b7f119ae3e --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-project.maybe_const_super.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `Self: ~const Uwu` is not satisfied + --> $DIR/const-project.rs:11:33 + | +LL | pub trait Owo::K }> {} + | ^^^^ the trait `~const Uwu` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | pub trait Owo::K }>: ~const Uwu {} + | ++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-project.never_const_super.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-project.never_const_super.stderr new file mode 100644 index 0000000000000..7b6b7f119ae3e --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-project.never_const_super.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `Self: ~const Uwu` is not satisfied + --> $DIR/const-project.rs:11:33 + | +LL | pub trait Owo::K }> {} + | ^^^^ the trait `~const Uwu` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | pub trait Owo::K }>: ~const Uwu {} + | ++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-project.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-project.rs new file mode 100644 index 0000000000000..dd784026c6470 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-project.rs @@ -0,0 +1,26 @@ +// revisions: never_const_super always_const_super maybe_const_super + +#![feature(const_trait_impl, effects)] +#![feature(associated_const_equality, generic_const_exprs)] +#![allow(incomplete_features)] + +// FIXME(effects): Shouldn't `{always,maybe}_const_super` pass? Also, why does +// the diagnostic message and location differ from `effects/project.rs`? + +#[const_trait] +pub trait Owo::K }> {} +//~^ ERROR the trait bound `Self: ~const Uwu` is not satisfied + +#[cfg(never_const_super)] +#[const_trait] +pub trait Uwu: Owo { const K: u32; } + +#[cfg(always_const_super)] +#[const_trait] +pub trait Uwu: const Owo { const K: u32; } + +#[cfg(maybe_const_super)] +#[const_trait] +pub trait Uwu: ~const Owo { const K: u32; } + +fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs index 84d9bcd7ac9f0..8a850a9cd1522 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs @@ -51,9 +51,8 @@ trait Try: FromResidual { fn branch(self) -> ControlFlow; } -// FIXME -// #[const_trait] -trait FromResidual::Residual> { +#[const_trait] +trait FromResidual::Residual> { #[lang = "from_residual"] fn from_residual(residual: R) -> Self; } diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.always-const-super.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.always-const-super.stderr new file mode 100644 index 0000000000000..7e81035e015bd --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.always-const-super.stderr @@ -0,0 +1,63 @@ +error[E0277]: the trait bound `Self: const Uwu` is not satisfied + --> $DIR/project.rs:22:1 + | +LL | pub trait Uwu: const Owo { type T; } + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `const Uwu` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | pub trait Uwu: const Owo + const Uwu { type T; } + | +++++++++++ + +error[E0277]: the trait bound `Self: const Uwu` is not satisfied + --> $DIR/project.rs:22:1 + | +LL | pub trait Uwu: const Owo { type T; } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `const Uwu` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | pub trait Uwu: const Owo + const Uwu { type T; } + | +++++++++++ + +error[E0277]: the trait bound `Self: const Uwu` is not satisfied + --> $DIR/project.rs:22:16 + | +LL | pub trait Uwu: const Owo { type T; } + | ^^^^^^^^^ the trait `const Uwu` is not implemented for `Self` + | +note: required by a bound in `Owo` + --> $DIR/project.rs:9:15 + | +LL | pub trait Owo::T> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Owo` +help: consider further restricting `Self` + | +LL | pub trait Uwu: const Owo + const Uwu { type T; } + | +++++++++++ + +error[E0277]: the trait bound `Self: const Uwu` is not satisfied + --> $DIR/project.rs:22:28 + | +LL | pub trait Uwu: const Owo { type T; } + | ^^^^^^ the trait `const Uwu` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | pub trait Uwu: const Owo + const Uwu { type T; } + | +++++++++++ + +error[E0277]: the trait bound `Self: const Uwu` is not satisfied + --> $DIR/project.rs:22:28 + | +LL | pub trait Uwu: const Owo { type T; } + | ^^^^^^^ the trait `const Uwu` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | pub trait Uwu: const Owo + const Uwu { type T; } + | +++++++++++ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.always_const_super.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.always_const_super.stderr new file mode 100644 index 0000000000000..d7d8467703a4a --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.always_const_super.stderr @@ -0,0 +1,63 @@ +error[E0277]: the trait bound `Self: const Uwu` is not satisfied + --> $DIR/project.rs:22:1 + | +LL | pub trait Uwu: const Owo { type T; } + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `const Uwu` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | pub trait Uwu: const Owo + const Uwu { type T; } + | +++++++++++ + +error[E0277]: the trait bound `Self: const Uwu` is not satisfied + --> $DIR/project.rs:22:1 + | +LL | pub trait Uwu: const Owo { type T; } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `const Uwu` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | pub trait Uwu: const Owo + const Uwu { type T; } + | +++++++++++ + +error[E0277]: the trait bound `Self: const Uwu` is not satisfied + --> $DIR/project.rs:22:16 + | +LL | pub trait Uwu: const Owo { type T; } + | ^^^^^^^^^ the trait `const Uwu` is not implemented for `Self` + | +note: required by a bound in `Owo` + --> $DIR/project.rs:7:15 + | +LL | pub trait Owo::T> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Owo` +help: consider further restricting `Self` + | +LL | pub trait Uwu: const Owo + const Uwu { type T; } + | +++++++++++ + +error[E0277]: the trait bound `Self: const Uwu` is not satisfied + --> $DIR/project.rs:22:28 + | +LL | pub trait Uwu: const Owo { type T; } + | ^^^^^^ the trait `const Uwu` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | pub trait Uwu: const Owo + const Uwu { type T; } + | +++++++++++ + +error[E0277]: the trait bound `Self: const Uwu` is not satisfied + --> $DIR/project.rs:22:28 + | +LL | pub trait Uwu: const Owo { type T; } + | ^^^^^^^ the trait `const Uwu` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | pub trait Uwu: const Owo + const Uwu { type T; } + | +++++++++++ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.never-const-super.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.never-const-super.stderr new file mode 100644 index 0000000000000..563eb3535c7a7 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.never-const-super.stderr @@ -0,0 +1,63 @@ +error[E0277]: the trait bound `Self: Uwu` is not satisfied + --> $DIR/project.rs:13:1 + | +LL | pub trait Uwu: Owo { type T; } + | ^^^^^^^^^^^^^^^^^^ the trait `Uwu` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | pub trait Uwu: Owo + Uwu { type T; } + | +++++ + +error[E0277]: the trait bound `Self: Uwu` is not satisfied + --> $DIR/project.rs:13:1 + | +LL | pub trait Uwu: Owo { type T; } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Uwu` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | pub trait Uwu: Owo + Uwu { type T; } + | +++++ + +error[E0277]: the trait bound `Self: Uwu` is not satisfied + --> $DIR/project.rs:13:16 + | +LL | pub trait Uwu: Owo { type T; } + | ^^^ the trait `Uwu` is not implemented for `Self` + | +note: required by a bound in `Owo` + --> $DIR/project.rs:9:15 + | +LL | pub trait Owo::T> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Owo` +help: consider further restricting `Self` + | +LL | pub trait Uwu: Owo + Uwu { type T; } + | +++++ + +error[E0277]: the trait bound `Self: Uwu` is not satisfied + --> $DIR/project.rs:13:22 + | +LL | pub trait Uwu: Owo { type T; } + | ^^^^^^ the trait `Uwu` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | pub trait Uwu: Owo + Uwu { type T; } + | +++++ + +error[E0277]: the trait bound `Self: Uwu` is not satisfied + --> $DIR/project.rs:13:22 + | +LL | pub trait Uwu: Owo { type T; } + | ^^^^^^^ the trait `Uwu` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | pub trait Uwu: Owo + Uwu { type T; } + | +++++ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.never_const_super.stderr similarity index 56% rename from tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.stderr rename to tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.never_const_super.stderr index eac3ee9e4e22b..b02af6b2cf2d8 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.never_const_super.stderr @@ -1,63 +1,61 @@ error[E0277]: the trait bound `Self: Uwu` is not satisfied --> $DIR/project.rs:12:1 | -LL | pub trait Uwu: Owo { +LL | pub trait Uwu: Owo { type T; } | ^^^^^^^^^^^^^^^^^^ the trait `Uwu` is not implemented for `Self` | help: consider further restricting `Self` | -LL | pub trait Uwu: Owo + Uwu { +LL | pub trait Uwu: Owo + Uwu { type T; } | +++++ error[E0277]: the trait bound `Self: Uwu` is not satisfied --> $DIR/project.rs:12:1 | -LL | / pub trait Uwu: Owo { -LL | | type T; -LL | | } - | |_^ the trait `Uwu` is not implemented for `Self` +LL | pub trait Uwu: Owo { type T; } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Uwu` is not implemented for `Self` | help: consider further restricting `Self` | -LL | pub trait Uwu: Owo + Uwu { +LL | pub trait Uwu: Owo + Uwu { type T; } | +++++ error[E0277]: the trait bound `Self: Uwu` is not satisfied --> $DIR/project.rs:12:16 | -LL | pub trait Uwu: Owo { +LL | pub trait Uwu: Owo { type T; } | ^^^ the trait `Uwu` is not implemented for `Self` | note: required by a bound in `Owo` - --> $DIR/project.rs:9:15 + --> $DIR/project.rs:7:15 | -LL | pub trait Owo::T> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Owo` +LL | pub trait Owo::T> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Owo` help: consider further restricting `Self` | -LL | pub trait Uwu: Owo + Uwu { +LL | pub trait Uwu: Owo + Uwu { type T; } | +++++ error[E0277]: the trait bound `Self: Uwu` is not satisfied - --> $DIR/project.rs:13:5 + --> $DIR/project.rs:12:22 | -LL | type T; - | ^^^^^^ the trait `Uwu` is not implemented for `Self` +LL | pub trait Uwu: Owo { type T; } + | ^^^^^^ the trait `Uwu` is not implemented for `Self` | help: consider further restricting `Self` | -LL | pub trait Uwu: Owo + Uwu { +LL | pub trait Uwu: Owo + Uwu { type T; } | +++++ error[E0277]: the trait bound `Self: Uwu` is not satisfied - --> $DIR/project.rs:13:5 + --> $DIR/project.rs:12:22 | -LL | type T; - | ^^^^^^^ the trait `Uwu` is not implemented for `Self` +LL | pub trait Uwu: Owo { type T; } + | ^^^^^^^ the trait `Uwu` is not implemented for `Self` | help: consider further restricting `Self` | -LL | pub trait Uwu: Owo + Uwu { +LL | pub trait Uwu: Owo + Uwu { type T; } | +++++ error: aborting due to 5 previous errors diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.rs index e22eed3e0ef57..29841947f6a79 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.rs @@ -1,16 +1,33 @@ -// known-bug: #110395 -// FIXME: effects +// revisions: never_const_super always_const_super maybe_const_super +//[maybe_const_super] check-pass #![feature(const_trait_impl, effects)] +#[const_trait] +pub trait Owo::T> {} + // This fails because `~const Uwu` doesn't imply (non-const) `Uwu`. +#[cfg(never_const_super)] +#[const_trait] +pub trait Uwu: Owo { type T; } +//[never_const_super]~^ ERROR the trait bound `Self: Uwu` is not satisfied +//[never_const_super]~| ERROR the trait bound `Self: Uwu` is not satisfied +//[never_const_super]~| ERROR the trait bound `Self: Uwu` is not satisfied +//[never_const_super]~| ERROR the trait bound `Self: Uwu` is not satisfied +//[never_const_super]~| ERROR the trait bound `Self: Uwu` is not satisfied -// FIXME: #[const_trait] -pub trait Owo::T> {} +// FIXME(effects): Shouldn't this pass? +#[cfg(always_const_super)] +#[const_trait] +pub trait Uwu: const Owo { type T; } +//[always_const_super]~^ ERROR the trait bound `Self: const Uwu` is not satisfied +//[always_const_super]~| ERROR the trait bound `Self: const Uwu` is not satisfied +//[always_const_super]~| ERROR the trait bound `Self: const Uwu` is not satisfied +//[always_const_super]~| ERROR the trait bound `Self: const Uwu` is not satisfied +//[always_const_super]~| ERROR the trait bound `Self: const Uwu` is not satisfied +#[cfg(maybe_const_super)] #[const_trait] -pub trait Uwu: Owo { - type T; -} +pub trait Uwu: ~const Owo { type T; } fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.gated.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.gated.stderr index 12f9355e41d4e..f48ef926e8d6c 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.gated.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.gated.stderr @@ -1,5 +1,5 @@ error: fatal error triggered by #[rustc_error] - --> $DIR/feature-gate.rs:22:1 + --> $DIR/feature-gate.rs:27:1 | LL | fn main() {} | ^^^^^^^^^ diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.rs index 015d90aaf21fa..65261cf1494a7 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.rs @@ -6,8 +6,8 @@ struct S; #[const_trait] //[stock]~ ERROR `const_trait` is a temporary placeholder -trait T {} -impl const T for S {} +trait T { type P; } +impl const T for S { type P = (); } //[stock]~^ ERROR const trait impls are experimental const fn f() {} //[stock]~ ERROR const trait impls are experimental @@ -18,5 +18,10 @@ macro_rules! discard { ($ty:ty) => {} } discard! { impl ~const T } //[stock]~ ERROR const trait impls are experimental discard! { impl const T } //[stock]~ ERROR const trait impls are experimental +const fn const_qualified_paths() { + let _: ::P; //[stock]~ ERROR const trait impls are experimental + let _: ::P; //[stock]~ ERROR const trait impls are experimental +} + #[rustc_error] fn main() {} //[gated]~ ERROR fatal error triggered by #[rustc_error] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.stock.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.stock.stderr index 78157d5705638..e9e2afbab0db1 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.stock.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.stock.stderr @@ -1,7 +1,7 @@ error[E0658]: const trait impls are experimental --> $DIR/feature-gate.rs:10:6 | -LL | impl const T for S {} +LL | impl const T for S { type P = (); } | ^^^^^ | = note: see issue #67792 for more information @@ -28,6 +28,26 @@ LL | fn g() {} = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +error[E0658]: const trait impls are experimental + --> $DIR/feature-gate.rs:22:18 + | +LL | let _: ::P; + | ^^^^^ + | + = note: see issue #67792 for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: const trait impls are experimental + --> $DIR/feature-gate.rs:23:18 + | +LL | let _: ::P; + | ^^^^^^ + | + = note: see issue #67792 for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + error[E0658]: const trait impls are experimental --> $DIR/feature-gate.rs:18:17 | @@ -58,6 +78,6 @@ LL | #[const_trait] = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 6 previous errors +error: aborting due to 8 previous errors For more information about this error, try `rustc --explain E0658`.