-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Trait-associated const fixes #25091
Trait-associated const fixes #25091
Changes from 3 commits
fbe8066
6665758
98f41ff
8db699d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3763,8 +3763,36 @@ pub fn resolve_ty_and_def_ufcs<'a, 'b, 'tcx>(fcx: &FnCtxt<'b, 'tcx>, | |
&'a [ast::PathSegment], | ||
def::Def)> | ||
{ | ||
|
||
// Associated constants can't depend on generic types. | ||
fn have_disallowed_generic_consts<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, | ||
def: def::Def, | ||
ty: Ty<'tcx>, | ||
span: Span, | ||
node_id: ast::NodeId) -> bool { | ||
match def { | ||
def::DefAssociatedConst(..) => { | ||
if ty::type_has_params(ty) || ty::type_has_self(ty) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we probably need to take lifetime parameters into account as well -- I don't know if there's an easy predicate to test for that, though. It seems like it'd be nice have a single flag for "NEEDS_SUBST" that applies to any type which references a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (Note that lifetime parameters on the trait will be early bound) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are you sure that lifetime parameters are relevant? The reason that type parameters are relevant is that they can influence the constant value that you end up with. I don't see how this could be true for lifetime parameters. E.g. I think that if
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
So, I think that lifetime parameters are as relevant as type parameters, but thinking on this a bit more I'm actually unclear on why the restriction on type parameters is needed. Am I missing something obvious? Perhaps you can spell out the scenario for me that you are concerned about? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a temporary restriction to prevent ICEs like #25046, until something like rust-lang/rfcs#1062 is implemented. Right now we expect to be able to evaluate constants in The only reason that a type parameter can affect the value of a const seems to be because it can affect which const we actually resolve to. This doesn't seem to be true of lifetime parameters, so I don't think that we need to worry about them. (And this makes some sense, because constants are... constant, more like statics or macros than something that's restricted to a particular region.) In any case, I haven't been able to construct an equivalent of #25046 that crashes due to a rogue lifetime parameter. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK, I see, I was a bit confused. As a temporary bypass for an ICE, this change (probably) makes sense. I thought at first you were imposing a more permanent restriction against associated constants whose types depending on type parameters -- and this didn't seem to make any sense to me, as I don't see any fundamental problem there. We do need to get our story straight about constants that cannot be resolved until trans, clearly -- seems to me that "constant equality" ought to be handled in a similar way to "type equality" in any case (and hence constant evaluation at type-check time is basically a form of normalization). But I have to finish a write-up talking about normalization and how we should consider a (mildly) different approach there too, so I guess it would apply equally. Anyway... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a tracking issue for this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think so. I'd like to get there, but have been tangled up in #22519 and related issues. |
||
fcx.sess().span_err(span, | ||
"Associated consts cannot depend \ | ||
on type parameters or Self."); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can you add a diagnostic (and associated code) use the |
||
fcx.write_error(node_id); | ||
return true; | ||
} | ||
} | ||
_ => {} | ||
} | ||
false | ||
} | ||
|
||
// If fully resolved already, we don't have to do anything. | ||
if path_res.depth == 0 { | ||
if let Some(ty) = opt_self_ty { | ||
if have_disallowed_generic_consts(fcx, path_res.full_def(), ty, | ||
span, node_id) { | ||
return None; | ||
} | ||
} | ||
Some((opt_self_ty, &path.segments, path_res.base_def)) | ||
} else { | ||
let mut def = path_res.base_def; | ||
|
@@ -3780,6 +3808,9 @@ pub fn resolve_ty_and_def_ufcs<'a, 'b, 'tcx>(fcx: &FnCtxt<'b, 'tcx>, | |
let item_name = item_segment.identifier.name; | ||
match method::resolve_ufcs(fcx, span, item_name, ty, node_id) { | ||
Ok((def, lp)) => { | ||
if have_disallowed_generic_consts(fcx, def, ty, span, node_id) { | ||
return None; | ||
} | ||
// Write back the new resolution. | ||
fcx.ccx.tcx.def_map.borrow_mut() | ||
.insert(node_id, def::PathResolution { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT | ||
// file at the top-level directory of this distribution and at | ||
// http://rust-lang.org/COPYRIGHT. | ||
// | ||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | ||
// option. This file may not be copied, modified, or distributed | ||
// except according to those terms. | ||
|
||
#![feature(associated_consts)] | ||
|
||
pub trait Foo { | ||
const MIN: i32; | ||
|
||
fn get_min() -> i32 { | ||
Self::MIN //~ Associated consts cannot depend on type parameters or Self. | ||
} | ||
} | ||
|
||
fn get_min<T: Foo>() -> i32 { | ||
T::MIN; //~ Associated consts cannot depend on type parameters or Self. | ||
<T as Foo>::MIN //~ Associated consts cannot depend on type parameters or Self. | ||
} | ||
|
||
fn main() {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT | ||
// file at the top-level directory of this distribution and at | ||
// http://rust-lang.org/COPYRIGHT. | ||
// | ||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | ||
// option. This file may not be copied, modified, or distributed | ||
// except according to those terms. | ||
|
||
#![feature(associated_consts)] | ||
|
||
struct Foo; | ||
|
||
trait HasNum { | ||
const NUM: isize; | ||
} | ||
impl HasNum for Foo { | ||
const NUM: isize = 1; | ||
} | ||
|
||
fn main() { | ||
assert!(match 2 { | ||
Foo::NUM ... 3 => true, | ||
_ => false, | ||
}); | ||
assert!(match 0 { | ||
-1 ... <Foo as HasNum>::NUM => true, | ||
_ => false, | ||
}); | ||
assert!(match 1 { | ||
<Foo as HasNum>::NUM ... <Foo>::NUM => true, | ||
_ => false, | ||
}); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the usual thing here is not to pass a closure, but rather a
Typer
-- but I'm not sure off-hand if we have a method getting the substs of an idThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, the other thing is that
const_eval
has to be working already incollect
, and I'm trying to get resolution of trait-associated constants working there. We don't haveClosureTyper
andParameterEnvironment
in play at that point, and it would be kind of funky to use them that early.