Auto merge of #71600 - Dylan-DPC:rollup-7tvzi9n, r=Dylan-DPC

Rollup of 6 pull requests

Successful merges:

 - #68716 (Stabilize `Span::mixed_site`)
 - #71263 (Remove unused abs_path method from rustc_span::source_map::FileLoader)
 - #71409 (Point at the return type on `.into()` failure caused by `?`)
 - #71419 (add message for resolution failure because wrong namespace)
 - #71438 (Tweak some suggestions in `rustc_resolve`)
 - #71589 (remove Unique::from for shared pointer types)

Failed merges:

r? @ghost
This commit is contained in:
bors 2020-04-27 02:38:50 +00:00
commit ef71df106b
21 changed files with 206 additions and 118 deletions

View File

@ -131,7 +131,7 @@ impl<K, V> BoxedNode<K, V> {
}
unsafe fn from_ptr(ptr: NonNull<LeafNode<K, V>>) -> Self {
BoxedNode { ptr: Unique::from(ptr) }
BoxedNode { ptr: Unique::new_unchecked(ptr.as_ptr()) }
}
fn as_ptr(&self) -> NonNull<LeafNode<K, V>> {

View File

@ -151,7 +151,7 @@ impl<T, A: AllocRef> RawVec<T, A> {
let memory = alloc.alloc(layout, init).unwrap_or_else(|_| handle_alloc_error(layout));
Self {
ptr: memory.ptr.cast().into(),
ptr: unsafe { Unique::new_unchecked(memory.ptr.cast().as_ptr()) },
cap: Self::capacity_from_bytes(memory.size),
alloc,
}
@ -469,7 +469,7 @@ impl<T, A: AllocRef> RawVec<T, A> {
}
fn set_memory(&mut self, memory: MemoryBlock) {
self.ptr = memory.ptr.cast().into();
self.ptr = unsafe { Unique::new_unchecked(memory.ptr.cast().as_ptr()) };
self.cap = Self::capacity_from_bytes(memory.size);
}

View File

@ -3,7 +3,6 @@ use crate::fmt;
use crate::marker::{PhantomData, Unsize};
use crate::mem;
use crate::ops::{CoerceUnsized, DispatchFromDyn};
use crate::ptr::NonNull;
// ignore-tidy-undocumented-unsafe
@ -171,19 +170,3 @@ impl<T: ?Sized> From<&mut T> for Unique<T> {
unsafe { Unique { pointer: reference as *mut T, _marker: PhantomData } }
}
}
#[unstable(feature = "ptr_internals", issue = "none")]
impl<T: ?Sized> From<&T> for Unique<T> {
#[inline]
fn from(reference: &T) -> Self {
unsafe { Unique { pointer: reference as *const T, _marker: PhantomData } }
}
}
#[unstable(feature = "ptr_internals", issue = "none")]
impl<T: ?Sized> From<NonNull<T>> for Unique<T> {
#[inline]
fn from(p: NonNull<T>) -> Self {
unsafe { Unique::new_unchecked(p.as_ptr()) }
}
}

View File

@ -303,7 +303,7 @@ impl Span {
/// definition site (local variables, labels, `$crate`) and sometimes at the macro
/// call site (everything else).
/// The span location is taken from the call-site.
#[unstable(feature = "proc_macro_mixed_site", issue = "65049")]
#[stable(feature = "proc_macro_mixed_site", since = "1.45.0")]
pub fn mixed_site() -> Span {
Span(bridge::client::Span::mixed_site())
}

View File

@ -383,7 +383,7 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
has_self_arg
}
fn followed_by_brace(&self, span: Span) -> (bool, Option<(Span, String)>) {
fn followed_by_brace(&self, span: Span) -> (bool, Option<Span>) {
// HACK(estebank): find a better way to figure out that this was a
// parser issue where a struct literal is being used on an expression
// where a brace being opened means a block is being started. Look
@ -406,7 +406,7 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
_ => false,
};
// In case this could be a struct literal that needs to be surrounded
// by parenthesis, find the appropriate span.
// by parentheses, find the appropriate span.
let mut i = 0;
let mut closing_brace = None;
loop {
@ -414,10 +414,7 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
match sm.span_to_snippet(sp) {
Ok(ref snippet) => {
if snippet == "}" {
let sp = span.to(sp);
if let Ok(snippet) = sm.span_to_snippet(sp) {
closing_brace = Some((sp, snippet));
}
closing_brace = Some(span.to(sp));
break;
}
}
@ -479,17 +476,23 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
suggested = path_sep(err, &parent);
}
PathSource::Expr(None) if followed_by_brace => {
if let Some((sp, snippet)) = closing_brace {
err.span_suggestion(
sp,
"surround the struct literal with parenthesis",
format!("({})", snippet),
if let Some(sp) = closing_brace {
err.multipart_suggestion(
"surround the struct literal with parentheses",
vec![
(sp.shrink_to_lo(), "(".to_string()),
(sp.shrink_to_hi(), ")".to_string()),
],
Applicability::MaybeIncorrect,
);
} else {
err.span_label(
span, // Note the parenthesis surrounding the suggestion below
format!("did you mean `({} {{ /* fields */ }})`?", path_str),
span, // Note the parentheses surrounding the suggestion below
format!(
"you might want to surround a struct literal with parentheses: \
`({} {{ /* fields */ }})`?",
path_str
),
);
}
suggested = true;
@ -516,10 +519,16 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
err.note("if you want the `try` keyword, you need to be in the 2018 edition");
}
}
(Res::Def(DefKind::TyAlias, _), PathSource::Trait(_)) => {
(Res::Def(DefKind::TyAlias, def_id), PathSource::Trait(_)) => {
err.span_label(span, "type aliases cannot be used as traits");
if nightly_options::is_nightly_build() {
err.note("did you mean to use a trait alias?");
let msg = "you might have meant to use `#![feature(trait_alias)]` instead of a \
`type` alias";
if let Some(span) = self.r.definitions.opt_span(def_id) {
err.span_help(span, msg);
} else {
err.help(msg);
}
}
}
(Res::Def(DefKind::Mod, _), PathSource::Expr(Some(parent))) => {

View File

@ -2066,52 +2066,64 @@ impl<'a> Resolver<'a> {
};
}
let binding = if let Some(module) = module {
self.resolve_ident_in_module(
module,
ident,
ns,
parent_scope,
record_used,
path_span,
)
} else if ribs.is_none() || opt_ns.is_none() || opt_ns == Some(MacroNS) {
let scopes = ScopeSet::All(ns, opt_ns.is_none());
self.early_resolve_ident_in_lexical_scope(
ident,
scopes,
parent_scope,
record_used,
record_used,
path_span,
)
} else {
let record_used_id =
if record_used { crate_lint.node_id().or(Some(CRATE_NODE_ID)) } else { None };
match self.resolve_ident_in_lexical_scope(
ident,
ns,
parent_scope,
record_used_id,
path_span,
&ribs.unwrap()[ns],
) {
// we found a locally-imported or available item/module
Some(LexicalScopeBinding::Item(binding)) => Ok(binding),
// we found a local variable or type param
Some(LexicalScopeBinding::Res(res))
if opt_ns == Some(TypeNS) || opt_ns == Some(ValueNS) =>
{
record_segment_res(self, res);
return PathResult::NonModule(PartialRes::with_unresolved_segments(
res,
path.len() - 1,
));
enum FindBindingResult<'a> {
Binding(Result<&'a NameBinding<'a>, Determinacy>),
PathResult(PathResult<'a>),
}
let find_binding_in_ns = |this: &mut Self, ns| {
let binding = if let Some(module) = module {
this.resolve_ident_in_module(
module,
ident,
ns,
parent_scope,
record_used,
path_span,
)
} else if ribs.is_none() || opt_ns.is_none() || opt_ns == Some(MacroNS) {
let scopes = ScopeSet::All(ns, opt_ns.is_none());
this.early_resolve_ident_in_lexical_scope(
ident,
scopes,
parent_scope,
record_used,
record_used,
path_span,
)
} else {
let record_used_id = if record_used {
crate_lint.node_id().or(Some(CRATE_NODE_ID))
} else {
None
};
match this.resolve_ident_in_lexical_scope(
ident,
ns,
parent_scope,
record_used_id,
path_span,
&ribs.unwrap()[ns],
) {
// we found a locally-imported or available item/module
Some(LexicalScopeBinding::Item(binding)) => Ok(binding),
// we found a local variable or type param
Some(LexicalScopeBinding::Res(res))
if opt_ns == Some(TypeNS) || opt_ns == Some(ValueNS) =>
{
record_segment_res(this, res);
return FindBindingResult::PathResult(PathResult::NonModule(
PartialRes::with_unresolved_segments(res, path.len() - 1),
));
}
_ => Err(Determinacy::determined(record_used)),
}
_ => Err(Determinacy::determined(record_used)),
}
};
FindBindingResult::Binding(binding)
};
let binding = match find_binding_in_ns(self, ns) {
FindBindingResult::PathResult(x) => return x,
FindBindingResult::Binding(binding) => binding,
};
match binding {
Ok(binding) => {
if i == 1 {
@ -2201,7 +2213,33 @@ impl<'a> Resolver<'a> {
} else if i == 0 {
(format!("use of undeclared type or module `{}`", ident), None)
} else {
(format!("could not find `{}` in `{}`", ident, path[i - 1].ident), None)
let mut msg =
format!("could not find `{}` in `{}`", ident, path[i - 1].ident);
if ns == TypeNS || ns == ValueNS {
let ns_to_try = if ns == TypeNS { ValueNS } else { TypeNS };
if let FindBindingResult::Binding(Ok(binding)) =
find_binding_in_ns(self, ns_to_try)
{
let mut found = |what| {
msg = format!(
"expected {}, found {} `{}` in `{}`",
ns.descr(),
what,
ident,
path[i - 1].ident
)
};
if binding.module().is_some() {
found("module")
} else {
match binding.res() {
def::Res::<NodeId>::Def(kind, id) => found(kind.descr(id)),
_ => found(ns_to_try.descr()),
}
}
};
}
(msg, None)
};
return PathResult::Failed {
span: ident.span,

View File

@ -20,7 +20,6 @@ use std::path::{Path, PathBuf};
use std::sync::atomic::Ordering;
use log::debug;
use std::env;
use std::fs;
use std::io;
@ -64,9 +63,6 @@ pub trait FileLoader {
/// Query the existence of a file.
fn file_exists(&self, path: &Path) -> bool;
/// Returns an absolute path to a file, if possible.
fn abs_path(&self, path: &Path) -> Option<PathBuf>;
/// Read the contents of an UTF-8 file into memory.
fn read_file(&self, path: &Path) -> io::Result<String>;
}
@ -79,14 +75,6 @@ impl FileLoader for RealFileLoader {
fs::metadata(path).is_ok()
}
fn abs_path(&self, path: &Path) -> Option<PathBuf> {
if path.is_absolute() {
Some(path.to_path_buf())
} else {
env::current_dir().ok().map(|cwd| cwd.join(path))
}
}
fn read_file(&self, path: &Path) -> io::Result<String> {
fs::read_to_string(path)
}

View File

@ -317,20 +317,30 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
.starts_with("std::convert::From<std::option::NoneError");
let should_convert_result_to_option = format!("{}", trait_ref)
.starts_with("<std::option::NoneError as std::convert::From<");
if is_try && is_from && should_convert_option_to_result {
err.span_suggestion_verbose(
span.shrink_to_lo(),
"consider converting the `Option<T>` into a `Result<T, _>` using `Option::ok_or` or `Option::ok_or_else`",
".ok_or_else(|| /* error value */)".to_string(),
Applicability::HasPlaceholders,
);
} else if is_try && is_from && should_convert_result_to_option {
err.span_suggestion_verbose(
span.shrink_to_lo(),
"consider converting the `Result<T, _>` into an `Option<T>` using `Result::ok`",
".ok()".to_string(),
Applicability::MachineApplicable,
);
if is_try && is_from {
if should_convert_option_to_result {
err.span_suggestion_verbose(
span.shrink_to_lo(),
"consider converting the `Option<T>` into a `Result<T, _>` \
using `Option::ok_or` or `Option::ok_or_else`",
".ok_or_else(|| /* error value */)".to_string(),
Applicability::HasPlaceholders,
);
} else if should_convert_result_to_option {
err.span_suggestion_verbose(
span.shrink_to_lo(),
"consider converting the `Result<T, _>` into an `Option<T>` \
using `Result::ok`",
".ok()".to_string(),
Applicability::MachineApplicable,
);
}
if let Some(ret_span) = self.return_type_span(obligation) {
err.span_label(
ret_span,
&format!("expected `{}` because of this", trait_ref.self_ty()),
);
}
}
let explanation =

View File

@ -84,6 +84,8 @@ pub trait InferCtxtExt<'tcx> {
trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
);
fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option<Span>;
fn suggest_impl_trait(
&self,
err: &mut DiagnosticBuilder<'tcx>,
@ -761,6 +763,17 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
}
}
fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option<Span> {
let hir = self.tcx.hir();
let parent_node = hir.get_parent_node(obligation.cause.body_id);
let sig = match hir.find(parent_node) {
Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, ..), .. })) => sig,
_ => return None,
};
if let hir::FnRetTy::Return(ret_ty) = sig.decl.output { Some(ret_ty.span) } else { None }
}
/// If all conditions are met to identify a returned `dyn Trait`, suggest using `impl Trait` if
/// applicable and signal that the error has been expanded appropriately and needs to be
/// emitted.

View File

@ -4,7 +4,11 @@ error[E0404]: expected trait, found type alias `Bar`
LL | impl Bar for Baz { }
| ^^^ type aliases cannot be used as traits
|
= note: did you mean to use a trait alias?
help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias
--> $DIR/two_files_data.rs:5:1
|
LL | type Bar = dyn Foo;
| ^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error

View File

@ -45,9 +45,12 @@ error[E0423]: expected value, found struct `T`
--> $DIR/E0423.rs:14:8
|
LL | if T {} == T {} { println!("Ok"); }
| ^---
| |
| help: surround the struct literal with parenthesis: `(T {})`
| ^
|
help: surround the struct literal with parentheses
|
LL | if (T {}) == T {} { println!("Ok"); }
| ^ ^
error: aborting due to 5 previous errors

View File

@ -1,6 +1,8 @@
error[E0277]: `?` couldn't convert the error to `()`
--> $DIR/issue-32709.rs:4:11
|
LL | fn a() -> Result<i32, ()> {
| --------------- expected `()` because of this
LL | Err(5)?;
| ^ the trait `std::convert::From<{integer}>` is not implemented for `()`
|

View File

@ -0,0 +1,6 @@
use std::sync::mpsc;
fn main() {
let (tx, rx) = mpsc::channel::new(1);
//~^ ERROR expected type, found function `channel` in `mpsc`
}

View File

@ -0,0 +1,9 @@
error[E0433]: failed to resolve: expected type, found function `channel` in `mpsc`
--> $DIR/issue-71406.rs:4:26
|
LL | let (tx, rx) = mpsc::channel::new(1);
| ^^^^^^^ expected type, found function `channel` in `mpsc`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0433`.

View File

@ -1,6 +1,9 @@
error[E0277]: `?` couldn't convert the error to `()`
--> $DIR/option-to-result.rs:5:6
|
LL | fn test_result() -> Result<(),()> {
| ------------- expected `()` because of this
LL | let a:Option<()> = Some(());
LL | a?;
| ^ the trait `std::convert::From<std::option::NoneError>` is not implemented for `()`
|
@ -14,6 +17,9 @@ LL | a.ok_or_else(|| /* error value */)?;
error[E0277]: `?` couldn't convert the error to `std::option::NoneError`
--> $DIR/option-to-result.rs:11:6
|
LL | fn test_option() -> Option<i32>{
| ----------- expected `std::option::NoneError` because of this
LL | let a:Result<i32, i32> = Ok(5);
LL | a?;
| ^ the trait `std::convert::From<i32>` is not implemented for `std::option::NoneError`
|

View File

@ -2,7 +2,6 @@
// no-prefer-dynamic
#![feature(proc_macro_hygiene)]
#![feature(proc_macro_mixed_site)]
#![feature(proc_macro_quote)]
#![crate_type = "proc-macro"]

View File

@ -4,7 +4,11 @@ error[E0404]: expected trait, found type alias `Foo`
LL | impl Foo for S {
| ^^^ type aliases cannot be used as traits
|
= note: did you mean to use a trait alias?
help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias
--> $DIR/issue-3907.rs:5:1
|
LL | type Foo = dyn issue_3907::Foo;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: possible better candidate is found in another module, you can import it into scope
|
LL | use issue_3907::Foo;

View File

@ -16,7 +16,11 @@ LL | impl K for isize {}
| type aliases cannot be used as traits
| help: a trait with a similar name exists: `I`
|
= note: did you mean to use a trait alias?
help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias
--> $DIR/issue-5035.rs:2:1
|
LL | type K = dyn I;
| ^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors

View File

@ -10,7 +10,11 @@ error[E0404]: expected trait, found type alias `Typedef`
LL | fn g<F:Typedef(isize) -> isize>(x: F) {}
| ^^^^^^^^^^^^^^^^^^^^^^^ type aliases cannot be used as traits
|
= note: did you mean to use a trait alias?
help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias
--> $DIR/unboxed-closure-sugar-nonexistent-trait.rs:4:1
|
LL | type Typedef = isize;
| ^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors

View File

@ -46,9 +46,12 @@ error[E0423]: expected value, found struct variant `E::V`
--> $DIR/struct-literal-variant-in-if.rs:10:13
|
LL | if x == E::V { field } {}
| ^^^^----------
| |
| help: surround the struct literal with parenthesis: `(E::V { field })`
| ^^^^
|
help: surround the struct literal with parentheses
|
LL | if x == (E::V { field }) {}
| ^ ^
error[E0308]: mismatched types
--> $DIR/struct-literal-variant-in-if.rs:10:20

View File

@ -1,6 +1,9 @@
error[E0277]: `?` couldn't convert the error to `()`
--> $DIR/try-on-option.rs:7:6
|
LL | fn foo() -> Result<u32, ()> {
| --------------- expected `()` because of this
LL | let x: Option<u32> = None;
LL | x?;
| ^ the trait `std::convert::From<std::option::NoneError>` is not implemented for `()`
|