From d744f36ea2f63a1f3f022885c30163c3835347b5 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Tue, 9 Aug 2022 17:41:49 +0000 Subject: [PATCH 1/4] Fix wf check on `#[const_trait]` return types --- compiler/rustc_typeck/src/check/wfcheck.rs | 38 ++++++++++++++++--- .../rfc-2632-const-trait-impl/issue-100222.rs | 14 +++++++ 2 files changed, 46 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/rfc-2632-const-trait-impl/issue-100222.rs diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 4814aea7afb9e..654a981d506e9 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -66,12 +66,18 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> { span: Span, loc: Option, arg: ty::GenericArg<'tcx>, + override_constness: Option, ) { let cause = traits::ObligationCause::new(span, self.body_id, ObligationCauseCode::WellFormed(loc)); + let param_env = if let Some(constness) = override_constness { + self.param_env.with_constness(constness) + } else { + self.param_env + }; self.ocx.register_obligation(traits::Obligation::new( cause, - self.param_env, + param_env, ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)).to_predicate(self.tcx()), )); } @@ -985,7 +991,7 @@ fn check_associated_item( ty::AssocKind::Const => { let ty = tcx.type_of(item.def_id); let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty); - wfcx.register_wf_obligation(span, loc, ty.into()); + wfcx.register_wf_obligation(span, loc, ty.into(), None); } ty::AssocKind::Fn => { let sig = tcx.fn_sig(item.def_id); @@ -1006,7 +1012,7 @@ fn check_associated_item( if item.defaultness(tcx).has_value() { let ty = tcx.type_of(item.def_id); let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty); - wfcx.register_wf_obligation(span, loc, ty.into()); + wfcx.register_wf_obligation(span, loc, ty.into(), None); } } } @@ -1042,6 +1048,7 @@ fn check_type_defn<'tcx, F>( field.span, Some(WellFormedLoc::Ty(field.def_id)), field.ty.into(), + None, ) } @@ -1191,7 +1198,12 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: LocalDefId, ty_span: Span, allow_fo } } - wfcx.register_wf_obligation(ty_span, Some(WellFormedLoc::Ty(item_id)), item_ty.into()); + wfcx.register_wf_obligation( + ty_span, + Some(WellFormedLoc::Ty(item_id)), + item_ty.into(), + None, + ); if forbid_unsized { wfcx.register_bound( traits::ObligationCause::new(ty_span, wfcx.body_id, traits::WellFormed(None)), @@ -1260,6 +1272,7 @@ fn check_impl<'tcx>( ast_self_ty.span, Some(WellFormedLoc::Ty(item.hir_id().expect_owner())), self_ty.into(), + None, ); } } @@ -1300,7 +1313,12 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id // parameter includes another (e.g., ``). In those cases, we can't // be sure if it will error or not as user might always specify the other. if !ty.needs_subst() { - wfcx.register_wf_obligation(tcx.def_span(param.def_id), None, ty.into()); + wfcx.register_wf_obligation( + tcx.def_span(param.def_id), + None, + ty.into(), + None, + ); } } } @@ -1316,6 +1334,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id tcx.def_span(param.def_id), None, default_ct.into(), + None, ); } } @@ -1496,10 +1515,17 @@ fn check_fn_or_method<'tcx>( ty.span, Some(WellFormedLoc::Param { function: def_id, param_idx: i.try_into().unwrap() }), input_ty.into(), + None, ); } - wfcx.register_wf_obligation(hir_decl.output.span(), None, sig.output().into()); + // override the env when checking the return type. `~const` bounds can be fulfilled with non-const implementations. + wfcx.register_wf_obligation( + hir_decl.output.span(), + None, + sig.output().into(), + Some(hir::Constness::NotConst), + ); check_where_clauses(wfcx, span, def_id); } diff --git a/src/test/ui/rfc-2632-const-trait-impl/issue-100222.rs b/src/test/ui/rfc-2632-const-trait-impl/issue-100222.rs new file mode 100644 index 0000000000000..40517ecdd6ce4 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/issue-100222.rs @@ -0,0 +1,14 @@ +// check-pass +#![feature(const_trait_impl)] + +#[const_trait] +pub trait Index { + type Output; +} + +#[const_trait] +pub trait IndexMut where Self: Index { + fn foo(&mut self) -> ::Output; +} + +fn main() {} From 460daf34346e621ad31ad68832a2c573aa723906 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Mon, 22 Aug 2022 11:06:07 +0000 Subject: [PATCH 2/4] remove stray comment --- compiler/rustc_typeck/src/check/wfcheck.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 654a981d506e9..4938181eea704 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -1519,7 +1519,6 @@ fn check_fn_or_method<'tcx>( ); } - // override the env when checking the return type. `~const` bounds can be fulfilled with non-const implementations. wfcx.register_wf_obligation( hir_decl.output.span(), None, From f019b6c5e8f2bb7e5985ea595b0946479c5aa4c2 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Mon, 22 Aug 2022 11:28:01 +0000 Subject: [PATCH 3/4] Overhaul 100222 test; wf always remap to nonconst --- compiler/rustc_typeck/src/check/wfcheck.rs | 21 +++++-------------- .../rfc-2632-const-trait-impl/issue-100222.rs | 21 +++++++++++++++---- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 4938181eea704..9e39abe9aa55b 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -66,15 +66,11 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> { span: Span, loc: Option, arg: ty::GenericArg<'tcx>, - override_constness: Option, ) { let cause = traits::ObligationCause::new(span, self.body_id, ObligationCauseCode::WellFormed(loc)); - let param_env = if let Some(constness) = override_constness { - self.param_env.with_constness(constness) - } else { - self.param_env - }; + // for a type to be WF, we do not need to check if const trait predicates satisfy. + let param_env = self.param_env.without_const(); self.ocx.register_obligation(traits::Obligation::new( cause, param_env, @@ -991,7 +987,7 @@ fn check_associated_item( ty::AssocKind::Const => { let ty = tcx.type_of(item.def_id); let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty); - wfcx.register_wf_obligation(span, loc, ty.into(), None); + wfcx.register_wf_obligation(span, loc, ty.into()); } ty::AssocKind::Fn => { let sig = tcx.fn_sig(item.def_id); @@ -1012,7 +1008,7 @@ fn check_associated_item( if item.defaultness(tcx).has_value() { let ty = tcx.type_of(item.def_id); let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty); - wfcx.register_wf_obligation(span, loc, ty.into(), None); + wfcx.register_wf_obligation(span, loc, ty.into()); } } } @@ -1048,7 +1044,6 @@ fn check_type_defn<'tcx, F>( field.span, Some(WellFormedLoc::Ty(field.def_id)), field.ty.into(), - None, ) } @@ -1202,7 +1197,6 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: LocalDefId, ty_span: Span, allow_fo ty_span, Some(WellFormedLoc::Ty(item_id)), item_ty.into(), - None, ); if forbid_unsized { wfcx.register_bound( @@ -1272,7 +1266,6 @@ fn check_impl<'tcx>( ast_self_ty.span, Some(WellFormedLoc::Ty(item.hir_id().expect_owner())), self_ty.into(), - None, ); } } @@ -1317,7 +1310,6 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id tcx.def_span(param.def_id), None, ty.into(), - None, ); } } @@ -1334,7 +1326,6 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id tcx.def_span(param.def_id), None, default_ct.into(), - None, ); } } @@ -1463,7 +1454,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id assert_eq!(predicates.predicates.len(), predicates.spans.len()); let wf_obligations = iter::zip(&predicates.predicates, &predicates.spans).flat_map(|(&p, &sp)| { - traits::wf::predicate_obligations(infcx, wfcx.param_env, wfcx.body_id, p, sp) + traits::wf::predicate_obligations(infcx, wfcx.param_env.without_const(), wfcx.body_id, p, sp) }); let obligations: Vec<_> = wf_obligations.chain(default_obligations).collect(); @@ -1515,7 +1506,6 @@ fn check_fn_or_method<'tcx>( ty.span, Some(WellFormedLoc::Param { function: def_id, param_idx: i.try_into().unwrap() }), input_ty.into(), - None, ); } @@ -1523,7 +1513,6 @@ fn check_fn_or_method<'tcx>( hir_decl.output.span(), None, sig.output().into(), - Some(hir::Constness::NotConst), ); check_where_clauses(wfcx, span, def_id); diff --git a/src/test/ui/rfc-2632-const-trait-impl/issue-100222.rs b/src/test/ui/rfc-2632-const-trait-impl/issue-100222.rs index 40517ecdd6ce4..2db5595a5aed2 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/issue-100222.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/issue-100222.rs @@ -1,14 +1,27 @@ +// revisions: nn ny yn yy // check-pass -#![feature(const_trait_impl)] +#![feature(const_trait_impl, associated_type_defaults, const_mut_refs)] -#[const_trait] +#[cfg_attr(any(yn, yy), const_trait)] pub trait Index { type Output; } -#[const_trait] +#[cfg_attr(any(ny, yy), const_trait)] pub trait IndexMut where Self: Index { - fn foo(&mut self) -> ::Output; + const C: ::Output; + type Assoc = ::Output; + fn foo(&mut self, x: ::Output) -> ::Output; } +impl Index for () { type Output = (); } + +impl const IndexMut for <() as Index>::Output { + const C: ::Output = (); + type Assoc = ::Output; + fn foo(&mut self, x: ::Output) -> ::Output where ::Output: {} +} + +const C: <() as Index>::Output = (); + fn main() {} From f1db3be9cf9a7efff0db8195e245dcfea16cb233 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Mon, 22 Aug 2022 11:41:38 +0000 Subject: [PATCH 4/4] fix tidy --- compiler/rustc_typeck/src/check/wfcheck.rs | 26 +++++++------------ .../rfc-2632-const-trait-impl/issue-100222.rs | 4 ++- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 9e39abe9aa55b..9e39e49b63c20 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -1193,11 +1193,7 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: LocalDefId, ty_span: Span, allow_fo } } - wfcx.register_wf_obligation( - ty_span, - Some(WellFormedLoc::Ty(item_id)), - item_ty.into(), - ); + wfcx.register_wf_obligation(ty_span, Some(WellFormedLoc::Ty(item_id)), item_ty.into()); if forbid_unsized { wfcx.register_bound( traits::ObligationCause::new(ty_span, wfcx.body_id, traits::WellFormed(None)), @@ -1306,11 +1302,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id // parameter includes another (e.g., ``). In those cases, we can't // be sure if it will error or not as user might always specify the other. if !ty.needs_subst() { - wfcx.register_wf_obligation( - tcx.def_span(param.def_id), - None, - ty.into(), - ); + wfcx.register_wf_obligation(tcx.def_span(param.def_id), None, ty.into()); } } } @@ -1454,7 +1446,13 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id assert_eq!(predicates.predicates.len(), predicates.spans.len()); let wf_obligations = iter::zip(&predicates.predicates, &predicates.spans).flat_map(|(&p, &sp)| { - traits::wf::predicate_obligations(infcx, wfcx.param_env.without_const(), wfcx.body_id, p, sp) + traits::wf::predicate_obligations( + infcx, + wfcx.param_env.without_const(), + wfcx.body_id, + p, + sp, + ) }); let obligations: Vec<_> = wf_obligations.chain(default_obligations).collect(); @@ -1509,11 +1507,7 @@ fn check_fn_or_method<'tcx>( ); } - wfcx.register_wf_obligation( - hir_decl.output.span(), - None, - sig.output().into(), - ); + wfcx.register_wf_obligation(hir_decl.output.span(), None, sig.output().into()); check_where_clauses(wfcx, span, def_id); } diff --git a/src/test/ui/rfc-2632-const-trait-impl/issue-100222.rs b/src/test/ui/rfc-2632-const-trait-impl/issue-100222.rs index 2db5595a5aed2..1004bb28c59e7 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/issue-100222.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/issue-100222.rs @@ -19,7 +19,9 @@ impl Index for () { type Output = (); } impl const IndexMut for <() as Index>::Output { const C: ::Output = (); type Assoc = ::Output; - fn foo(&mut self, x: ::Output) -> ::Output where ::Output: {} + fn foo(&mut self, x: ::Output) -> ::Output + where ::Output:, + {} } const C: <() as Index>::Output = ();