diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 04240bf2875746dc6644f5cc73ae16c87fee23a0..0bfb830efc1e77b4c17112118cb38ccdbe5701ea 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -112,7 +112,9 @@ use dep_graph::DepNode; use middle::def::*; use middle::pat_util; -use middle::ty::{self, TyCtxt}; +use middle::ty::{self, TyCtxt, ParameterEnvironment}; +use middle::traits::{self, ProjectionMode}; +use middle::infer; use lint; use util::nodemap::NodeMap; @@ -1490,9 +1492,19 @@ fn check_ret(&self, match fn_ret { ty::FnConverging(t_ret) - if self.live_on_entry(entry_ln, self.s.no_ret_var).is_some() => { - - if t_ret.is_nil() { + if self.live_on_entry(entry_ln, self.s.no_ret_var).is_some() => { + + let param_env = ParameterEnvironment::for_item(&self.ir.tcx, id); + let infcx = infer::new_infer_ctxt(&self.ir.tcx, + &self.ir.tcx.tables, + Some(param_env), + ProjectionMode::Any); + let cause = traits::ObligationCause::dummy(); + let norm = traits::fully_normalize(&infcx, + cause, + &t_ret); + + if norm.unwrap().is_nil() { // for nil return types, it is ok to not return a value expl. } else { let ends_with_stmt = match body.expr { diff --git a/src/test/run-pass/issue-31597.rs b/src/test/run-pass/issue-31597.rs new file mode 100644 index 0000000000000000000000000000000000000000..9acd6384b75e5519dc739280e17c2e3d477129e4 --- /dev/null +++ b/src/test/run-pass/issue-31597.rs @@ -0,0 +1,37 @@ +// Copyright 2016 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait Make { + type Out; + + fn make() -> Self::Out; +} + +impl Make for () { + type Out = (); + + fn make() -> Self::Out {} +} + +// Also make sure we don't hit an ICE when the projection can't be known +fn f() -> ::Out { loop {} } + +// ...and that it works with a blanket impl +trait Tr { + type Assoc; +} + +impl Tr for T { + type Assoc = (); +} + +fn g() -> ::Assoc { } + +fn main() {}