Skip to content

Commit

Permalink
permit coercions if [error] is found in either type
Browse files Browse the repository at this point in the history
  • Loading branch information
nikomatsakis committed Jan 9, 2016
1 parent a3cbfa5 commit 83710b4
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 30 deletions.
55 changes: 27 additions & 28 deletions src/librustc_typeck/check/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ use middle::traits::{predicate_for_trait_def, report_selection_error};
use middle::ty::adjustment::{AutoAdjustment, AutoDerefRef, AdjustDerefRef};
use middle::ty::adjustment::{AutoPtr, AutoUnsafe, AdjustReifyFnPointer};
use middle::ty::adjustment::{AdjustUnsafeFnPointer};
use middle::ty::{self, LvaluePreference, TypeAndMut, Ty};
use middle::ty::{self, LvaluePreference, TypeAndMut, Ty, HasTypeFlags};
use middle::ty::error::TypeError;
use middle::ty::relate::RelateResult;
use util::common::indent;
Expand Down Expand Up @@ -110,10 +110,15 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
a,
b);

let a = self.fcx.infcx().shallow_resolve(a);

// Just ignore error types.
if a.references_error() || b.references_error() {
return Ok(None);
}

// Consider coercing the subtype to a DST
let unsize = self.unpack_actual_value(a, |a| {
self.coerce_unsized(a, b)
});
let unsize = self.coerce_unsized(a, b);
if unsize.is_ok() {
return unsize;
}
Expand All @@ -124,39 +129,33 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
// See above for details.
match b.sty {
ty::TyRawPtr(mt_b) => {
return self.unpack_actual_value(a, |a| {
self.coerce_unsafe_ptr(a, b, mt_b.mutbl)
});
return self.coerce_unsafe_ptr(a, b, mt_b.mutbl);
}

ty::TyRef(_, mt_b) => {
return self.unpack_actual_value(a, |a| {
self.coerce_borrowed_pointer(expr_a, a, b, mt_b.mutbl)
});
return self.coerce_borrowed_pointer(expr_a, a, b, mt_b.mutbl);
}

_ => {}
}

self.unpack_actual_value(a, |a| {
match a.sty {
ty::TyBareFn(Some(_), a_f) => {
// Function items are coercible to any closure
// type; function pointers are not (that would
// require double indirection).
self.coerce_from_fn_item(a, a_f, b)
}
ty::TyBareFn(None, a_f) => {
// We permit coercion of fn pointers to drop the
// unsafe qualifier.
self.coerce_from_fn_pointer(a, a_f, b)
}
_ => {
// Otherwise, just use subtyping rules.
self.subtype(a, b)
}
match a.sty {
ty::TyBareFn(Some(_), a_f) => {
// Function items are coercible to any closure
// type; function pointers are not (that would
// require double indirection).
self.coerce_from_fn_item(a, a_f, b)
}
})
ty::TyBareFn(None, a_f) => {
// We permit coercion of fn pointers to drop the
// unsafe qualifier.
self.coerce_from_fn_pointer(a, a_f, b)
}
_ => {
// Otherwise, just use subtyping rules.
self.subtype(a, b)
}
}
}

/// Reborrows `&mut A` to `&mut B` and `&(mut) A` to `&B`.
Expand Down
2 changes: 1 addition & 1 deletion src/test/compile-fail/issue-19692.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ struct Homura;

fn akemi(homura: Homura) {
let Some(ref madoka) = Some(homura.kaname()); //~ ERROR no method named `kaname` found
madoka.clone();
madoka.clone(); //~ ERROR the type of this value must be known
}

fn main() { }
2 changes: 1 addition & 1 deletion src/test/compile-fail/issue-3973.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,5 @@ impl ToString_ for Point {
fn main() {
let p = Point::new(0.0, 0.0);
//~^ ERROR no associated item named `new` found for type `Point` in the current scope
println!("{}", p.to_string());
println!("{}", p.to_string()); //~ ERROR type of this value must be known
}

0 comments on commit 83710b4

Please sign in to comment.