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

Rollup of 6 pull requests #65177

Closed
wants to merge 24 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
a5d9310
remove 'as_str' when it's already a str type.
Sep 24, 2019
bb3c030
add test files
Sep 24, 2019
4cb86c9
comment fixes
Sep 25, 2019
5abc5e9
add FIXME and use 'span_label'
Oct 1, 2019
51482d0
fix unit tests
Oct 1, 2019
11c2d43
typo fix in the code
Oct 2, 2019
55ecb79
Note when a mutable trait object is needed
estebank Oct 4, 2019
f5e372a
Tweak wording
estebank Oct 4, 2019
4414068
Correctly estimate required space for string
AnthonyMikh Oct 5, 2019
35a3b58
Obligation must apply modulo regions
estebank Oct 5, 2019
169b040
review comments
estebank Oct 5, 2019
0b0aeac
Suggest dereferencing boolean reference when used in 'if' or 'while'
XiangQingW Oct 6, 2019
8a164ac
Suggest dereferencing boolean reference when used in 'if' or 'while'
XiangQingW Oct 6, 2019
bbb69d1
Suggest dereferencing boolean reference when used in 'if' or 'while'
XiangQingW Oct 6, 2019
c5e0d6e
Add long error explanation for E0566
GuillaumeGomez Oct 6, 2019
57cb881
Update ui tests
GuillaumeGomez Oct 6, 2019
8baf7bf
Update reference
tmandry Oct 6, 2019
6efcb02
review comments
estebank Oct 7, 2019
c100831
Rollup merge of #64739 - guanqun:remove-as-str, r=estebank
Centril Oct 7, 2019
fa961fa
Rollup merge of #65077 - estebank:mut-trait-expected, r=nikomatsakis
Centril Oct 7, 2019
a3d0c90
Rollup merge of #65120 - AnthonyMikh:fix_65119, r=estebank
Centril Oct 7, 2019
934f3c2
Rollup merge of #65150 - XiangQingW:master, r=estebank
Centril Oct 7, 2019
00315c3
Rollup merge of #65164 - GuillaumeGomez:long-err-explanation-E0566, r…
Centril Oct 7, 2019
ca3f01a
Rollup merge of #65173 - tmandry:reffy-ref, r=tmandry
Centril Oct 7, 2019
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
2 changes: 1 addition & 1 deletion src/doc/reference
22 changes: 21 additions & 1 deletion src/librustc/error_codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1700,6 +1700,27 @@ To understand better how closures work in Rust, read:
https://doc.rust-lang.org/book/ch13-01-closures.html
"##,

E0566: r##"
Conflicting representation hints have been used on a same item.

Erroneous code example:

```
#[repr(u32, u64)] // warning!
enum Repr { A }
```

In most cases (if not all), using just one representation hint is more than
enough. If you want to have a representation hint depending on the current
architecture, use `cfg_attr`. Example:

```
#[cfg_attr(linux, repr(u32))]
#[cfg_attr(not(linux), repr(u64))]
enum Repr { A }
```
"##,

E0580: r##"
The `main` function was incorrectly declared.

Expand Down Expand Up @@ -2097,7 +2118,6 @@ rejected in your own crates.
E0490, // a value of type `..` is borrowed for too long
E0495, // cannot infer an appropriate lifetime due to conflicting
// requirements
E0566, // conflicting representation hints
E0623, // lifetime mismatch where both parameters are anonymous regions
E0628, // generators cannot have explicit parameters
E0631, // type mismatch in closure arguments
Expand Down
7 changes: 7 additions & 0 deletions src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1053,6 +1053,13 @@ impl Mutability {
MutImmutable => MutImmutable,
}
}

pub fn invert(self) -> Self {
match self {
MutMutable => MutImmutable,
MutImmutable => MutMutable,
}
}
}

#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Hash, HashStable)]
Expand Down
114 changes: 93 additions & 21 deletions src/librustc/traits/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -453,21 +453,17 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
}

fn find_similar_impl_candidates(&self,
trait_ref: ty::PolyTraitRef<'tcx>)
-> Vec<ty::TraitRef<'tcx>>
{
let simp = fast_reject::simplify_type(self.tcx,
trait_ref.skip_binder().self_ty(),
true);
fn find_similar_impl_candidates(
&self,
trait_ref: ty::PolyTraitRef<'tcx>,
) -> Vec<ty::TraitRef<'tcx>> {
let simp = fast_reject::simplify_type(self.tcx, trait_ref.skip_binder().self_ty(), true);
let all_impls = self.tcx.all_impls(trait_ref.def_id());

match simp {
Some(simp) => all_impls.iter().filter_map(|&def_id| {
let imp = self.tcx.impl_trait_ref(def_id).unwrap();
let imp_simp = fast_reject::simplify_type(self.tcx,
imp.self_ty(),
true);
let imp_simp = fast_reject::simplify_type(self.tcx, imp.self_ty(), true);
if let Some(imp_simp) = imp_simp {
if simp != imp_simp {
return None
Expand All @@ -482,10 +478,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
}

fn report_similar_impl_candidates(&self,
impl_candidates: Vec<ty::TraitRef<'tcx>>,
err: &mut DiagnosticBuilder<'_>)
{
fn report_similar_impl_candidates(
&self,
impl_candidates: Vec<ty::TraitRef<'tcx>>,
err: &mut DiagnosticBuilder<'_>,
) {
if impl_candidates.is_empty() {
return;
}
Expand Down Expand Up @@ -720,10 +717,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
// which is somewhat confusing.
err.help(&format!("consider adding a `where {}` bound",
trait_ref.to_predicate()));
} else if !have_alt_message {
// Can't show anything else useful, try to find similar impls.
let impl_candidates = self.find_similar_impl_candidates(trait_ref);
self.report_similar_impl_candidates(impl_candidates, &mut err);
} else {
if !have_alt_message {
// Can't show anything else useful, try to find similar impls.
let impl_candidates = self.find_similar_impl_candidates(trait_ref);
self.report_similar_impl_candidates(impl_candidates, &mut err);
}
self.suggest_change_mut(
&obligation,
&mut err,
&trait_ref,
points_at_arg,
);
}

// If this error is due to `!: Trait` not implemented but `(): Trait` is
Expand Down Expand Up @@ -1081,9 +1086,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {

let substs = self.tcx.mk_substs_trait(trait_type, &[]);
let new_trait_ref = ty::TraitRef::new(trait_ref.def_id, substs);
let new_obligation = Obligation::new(ObligationCause::dummy(),
obligation.param_env,
new_trait_ref.to_predicate());
let new_obligation = Obligation::new(
ObligationCause::dummy(),
obligation.param_env,
new_trait_ref.to_predicate(),
);

if self.predicate_may_hold(&new_obligation) {
let sp = self.tcx.sess.source_map()
Expand All @@ -1105,6 +1112,71 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
}

/// Check if the trait bound is implemented for a different mutability and note it in the
/// final error.
fn suggest_change_mut(
&self,
obligation: &PredicateObligation<'tcx>,
err: &mut DiagnosticBuilder<'tcx>,
trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
points_at_arg: bool,
) {
let span = obligation.cause.span;
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
let refs_number = snippet.chars()
.filter(|c| !c.is_whitespace())
.take_while(|c| *c == '&')
.count();
if let Some('\'') = snippet.chars()
.filter(|c| !c.is_whitespace())
.skip(refs_number)
.next()
{ // Do not suggest removal of borrow from type arguments.
return;
}

if let ty::Ref(region, t_type, mutability) = trait_ref.skip_binder().self_ty().kind {
let trait_type = match mutability {
hir::Mutability::MutMutable => self.tcx.mk_imm_ref(region, t_type),
hir::Mutability::MutImmutable => self.tcx.mk_mut_ref(region, t_type),
};

let substs = self.tcx.mk_substs_trait(&trait_type, &[]);
let new_trait_ref = ty::TraitRef::new(trait_ref.skip_binder().def_id, substs);
let new_obligation = Obligation::new(
ObligationCause::dummy(),
obligation.param_env,
new_trait_ref.to_predicate(),
);

if self.evaluate_obligation_no_overflow(
&new_obligation,
).must_apply_modulo_regions() {
let sp = self.tcx.sess.source_map()
.span_take_while(span, |c| c.is_whitespace() || *c == '&');
if points_at_arg &&
mutability == hir::Mutability::MutImmutable &&
refs_number > 0
{
err.span_suggestion(
sp,
"consider changing this borrow's mutability",
"&mut ".to_string(),
Applicability::MachineApplicable,
);
} else {
err.note(&format!(
"`{}` is implemented for `{:?}`, but not for `{:?}`",
trait_ref,
trait_type,
trait_ref.skip_binder().self_ty(),
));
}
}
}
}
}

fn suggest_semicolon_removal(
&self,
obligation: &PredicateObligation<'tcx>,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/traits/query/evaluate_obligation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
// Helper function that canonicalizes and runs the query. If an
// overflow results, we re-run it in the local context so we can
// report a nice error.
fn evaluate_obligation_no_overflow(
crate fn evaluate_obligation_no_overflow(
&self,
obligation: &PredicateObligation<'tcx>,
) -> EvaluationResult {
Expand Down
4 changes: 4 additions & 0 deletions src/librustc/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1775,6 +1775,10 @@ impl<'tcx> TyS<'tcx> {
#[inline]
pub fn is_bool(&self) -> bool { self.kind == Bool }

/// Returns `true` if this type is a `str`.
#[inline]
pub fn is_str(&self) -> bool { self.kind == Str }

#[inline]
pub fn is_param(&self, index: u32) -> bool {
match self.kind {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_errors/styled_buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ impl StyledBuffer {

pub fn prepend(&mut self, line: usize, string: &str, style: Style) {
self.ensure_lines(line);
let string_len = string.len();
let string_len = string.chars().count();

// Push the old content over to make room for new content
for _ in 0..string_len {
Expand Down
6 changes: 5 additions & 1 deletion src/librustc_typeck/check/demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

// If the span is from a macro, then it's hard to extract the text
// and make a good suggestion, so don't bother.
let is_macro = sp.from_expansion();
let is_desugaring = match sp.desugaring_kind() {
Some(k) => sp.is_desugaring(k),
None => false
};
let is_macro = sp.from_expansion() && !is_desugaring;

match (&expr.kind, &expected.kind, &checked_ty.kind) {
(_, &ty::Ref(_, exp, _), &ty::Ref(_, check, _)) => match (&exp.kind, &check.kind) {
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_typeck/check/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}

if let Some(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) {
self.suggest_ref_or_into(&mut err, expr, expected_ty, ty);

let expr = match &expr.kind {
ExprKind::DropTemps(expr) => expr,
_ => expr,
Expand Down
64 changes: 40 additions & 24 deletions src/librustc_typeck/check/method/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ pub enum MethodError<'tcx> {

// Found a `Self: Sized` bound where `Self` is a trait object, also the caller may have
// forgotten to import a trait.
IllegalSizedBound(Vec<DefId>),
IllegalSizedBound(Vec<DefId>, bool),

// Found a match, but the return type is wrong
BadReturnType,
Expand Down Expand Up @@ -213,33 +213,49 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
segment,
);

let mut needs_mut = false;
if let ty::Ref(region, t_type, mutability) = self_ty.kind {
let trait_type = self.tcx.mk_ref(region, ty::TypeAndMut {
ty: t_type,
mutbl: mutability.invert(),
});
match self.lookup_probe(
span,
segment.ident,
trait_type,
call_expr,
ProbeScope::TraitsInScope
) {
Ok(ref new_pick) if *new_pick != pick => {
needs_mut = true;
}
_ => {}
}
}

if result.illegal_sized_bound {
// We probe again, taking all traits into account (not only those in scope).
let candidates =
match self.lookup_probe(span,
segment.ident,
self_ty,
call_expr,
ProbeScope::AllTraits) {

// If we find a different result the caller probably forgot to import a trait.
Ok(ref new_pick) if *new_pick != pick => vec![new_pick.item.container.id()],
Err(Ambiguity(ref sources)) => {
sources.iter()
.filter_map(|source| {
match *source {
// Note: this cannot come from an inherent impl,
// because the first probing succeeded.
ImplSource(def) => self.tcx.trait_id_of_impl(def),
TraitSource(_) => None,
}
})
.collect()
let candidates = match self.lookup_probe(
span,
segment.ident,
self_ty,
call_expr,
ProbeScope::AllTraits,
) {
// If we find a different result the caller probably forgot to import a trait.
Ok(ref new_pick) if *new_pick != pick => vec![new_pick.item.container.id()],
Err(Ambiguity(ref sources)) => sources.iter().filter_map(|source| {
match *source {
// Note: this cannot come from an inherent impl,
// because the first probing succeeded.
ImplSource(def) => self.tcx.trait_id_of_impl(def),
TraitSource(_) => None,
}
_ => Vec::new(),
};
}).collect(),
_ => Vec::new(),
};

return Err(IllegalSizedBound(candidates));
return Err(IllegalSizedBound(candidates, needs_mut));
}

Ok(result.callee)
Expand Down
Loading