Skip to content
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

resolve: Fix two issues in fresh binding disambiguation #70006

Merged
merged 1 commit into from
Mar 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/librustc_mir_build/hair/pattern/check_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ impl PatCtxt<'_, '_> {
PatternError::AssocConstInPattern(span) => {
self.span_e0158(span, "associated consts cannot be referenced in patterns")
}
PatternError::ConstParamInPattern(span) => {
self.span_e0158(span, "const parameters cannot be referenced in patterns")
}
PatternError::FloatBug => {
// FIXME(#31407) this is only necessary because float parsing is buggy
::rustc::mir::interpret::struct_error(
Expand Down
7 changes: 6 additions & 1 deletion src/librustc_mir_build/hair/pattern/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ use std::fmt;
#[derive(Clone, Debug)]
crate enum PatternError {
AssocConstInPattern(Span),
ConstParamInPattern(Span),
StaticInPattern(Span),
FloatBug,
NonConstPath(Span),
Expand Down Expand Up @@ -727,7 +728,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
| Res::SelfCtor(..) => PatKind::Leaf { subpatterns },

_ => {
self.errors.push(PatternError::NonConstPath(span));
let pattern_error = match res {
Res::Def(DefKind::ConstParam, _) => PatternError::ConstParamInPattern(span),
_ => PatternError::NonConstPath(span),
};
self.errors.push(pattern_error);
PatKind::Wild
}
};
Expand Down
39 changes: 24 additions & 15 deletions src/librustc_resolve/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1517,21 +1517,33 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
ident: Ident,
has_sub: bool,
) -> Option<Res> {
let binding =
self.resolve_ident_in_lexical_scope(ident, ValueNS, None, pat.span)?.item()?;
let res = binding.res();
let ls_binding = self.resolve_ident_in_lexical_scope(ident, ValueNS, None, pat.span)?;
let (res, binding) = match ls_binding {
LexicalScopeBinding::Item(binding) if binding.is_ambiguity() => {
// For ambiguous bindings we don't know all their definitions and cannot check
// whether they can be shadowed by fresh bindings or not, so force an error.
self.r.record_use(ident, ValueNS, binding, false);
return None;
}
LexicalScopeBinding::Item(binding) => (binding.res(), Some(binding)),
LexicalScopeBinding::Res(res) => (res, None),
};

// An immutable (no `mut`) by-value (no `ref`) binding pattern without
// a sub pattern (no `@ $pat`) is syntactically ambiguous as it could
// also be interpreted as a path to e.g. a constant, variant, etc.
let is_syntactic_ambiguity = !has_sub && bm == BindingMode::ByValue(Mutability::Not);

match res {
Res::Def(DefKind::Ctor(_, CtorKind::Const), _) | Res::Def(DefKind::Const, _)
Res::Def(DefKind::Ctor(_, CtorKind::Const), _)
| Res::Def(DefKind::Const, _)
| Res::Def(DefKind::ConstParam, _)
if is_syntactic_ambiguity =>
{
// Disambiguate in favor of a unit struct/variant or constant pattern.
self.r.record_use(ident, ValueNS, binding, false);
if let Some(binding) = binding {
self.r.record_use(ident, ValueNS, binding, false);
}
Some(res)
}
Res::Def(DefKind::Ctor(..), _)
Expand All @@ -1547,23 +1559,20 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
ResolutionError::BindingShadowsSomethingUnacceptable(
pat_src.descr(),
ident.name,
binding,
binding.expect("no binding for a ctor or static"),
),
);
None
}
Res::Def(DefKind::Fn, _) | Res::Err => {
Res::Def(DefKind::Fn, _) | Res::Local(..) | Res::Err => {
// These entities are explicitly allowed to be shadowed by fresh bindings.
None
}
res => {
span_bug!(
ident.span,
"unexpected resolution for an \
identifier in pattern: {:?}",
res
);
}
_ => span_bug!(
ident.span,
"unexpected resolution for an identifier in pattern: {:?}",
res
),
}
}

Expand Down
7 changes: 0 additions & 7 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -323,13 +323,6 @@ enum LexicalScopeBinding<'a> {
}

impl<'a> LexicalScopeBinding<'a> {
fn item(self) -> Option<&'a NameBinding<'a>> {
match self {
LexicalScopeBinding::Item(binding) => Some(binding),
_ => None,
}
}

fn res(self) -> Res {
match self {
LexicalScopeBinding::Item(binding) => binding.res(),
Expand Down
3 changes: 2 additions & 1 deletion src/librustc_typeck/check/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -716,7 +716,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Res::Def(DefKind::Ctor(_, CtorKind::Const), _)
| Res::SelfCtor(..)
| Res::Def(DefKind::Const, _)
| Res::Def(DefKind::AssocConst, _) => {} // OK
| Res::Def(DefKind::AssocConst, _)
| Res::Def(DefKind::ConstParam, _) => {} // OK
_ => bug!("unexpected pattern resolution: {:?}", res),
}

Expand Down
18 changes: 18 additions & 0 deletions src/test/ui/binding/ambiguity-item.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Identifier pattern referring to an ambiguity item is an error (issue #46079).

mod m {
pub fn f() {}
}
use m::*;

mod n {
pub fn f() {}
}
use n::*; // OK, no conflict with `use m::*;`

fn main() {
let v = f; //~ ERROR `f` is ambiguous
match v {
f => {} //~ ERROR `f` is ambiguous
}
}
41 changes: 41 additions & 0 deletions src/test/ui/binding/ambiguity-item.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
error[E0659]: `f` is ambiguous (glob import vs glob import in the same module)
--> $DIR/ambiguity-item.rs:14:13
|
LL | let v = f;
| ^ ambiguous name
|
note: `f` could refer to the function imported here
--> $DIR/ambiguity-item.rs:6:5
|
LL | use m::*;
| ^^^^
= help: consider adding an explicit import of `f` to disambiguate
note: `f` could also refer to the function imported here
--> $DIR/ambiguity-item.rs:11:5
|
LL | use n::*; // OK, no conflict with `use m::*;`
| ^^^^
= help: consider adding an explicit import of `f` to disambiguate

error[E0659]: `f` is ambiguous (glob import vs glob import in the same module)
--> $DIR/ambiguity-item.rs:16:9
|
LL | f => {}
| ^ ambiguous name
|
note: `f` could refer to the function imported here
--> $DIR/ambiguity-item.rs:6:5
|
LL | use m::*;
| ^^^^
= help: consider adding an explicit import of `f` to disambiguate
note: `f` could also refer to the function imported here
--> $DIR/ambiguity-item.rs:11:5
|
LL | use n::*; // OK, no conflict with `use m::*;`
| ^^^^
= help: consider adding an explicit import of `f` to disambiguate

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0659`.
12 changes: 12 additions & 0 deletions src/test/ui/binding/const-param.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Identifier pattern referring to a const generic parameter is an error (issue #68853).

#![feature(const_generics)] //~ WARN the feature `const_generics` is incomplete

fn check<const N: usize>() {
match 1 {
N => {} //~ ERROR const parameters cannot be referenced in patterns
_ => {}
}
}

fn main() {}
17 changes: 17 additions & 0 deletions src/test/ui/binding/const-param.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
--> $DIR/const-param.rs:3:12
|
LL | #![feature(const_generics)]
| ^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default

error[E0158]: const parameters cannot be referenced in patterns
--> $DIR/const-param.rs:7:9
|
LL | N => {}
| ^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0158`.