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 #98691

Merged
merged 14 commits into from
Jun 30, 2022
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
21 changes: 7 additions & 14 deletions compiler/rustc_infer/src/infer/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use hir::{HirId, OpaqueTyOrigin};
use rustc_data_structures::sync::Lrc;
use rustc_data_structures::vec_map::VecMap;
use rustc_hir as hir;
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::fold::BottomUpFolder;
use rustc_middle::ty::subst::{GenericArgKind, Subst};
use rustc_middle::ty::{
Expand Down Expand Up @@ -44,30 +44,23 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
ty: Ty<'tcx>,
body_id: HirId,
span: Span,
code: ObligationCauseCode<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> InferOk<'tcx, Ty<'tcx>> {
if !ty.has_opaque_types() {
return InferOk { value: ty, obligations: vec![] };
}
let mut obligations = vec![];
let replace_opaque_type = |def_id| self.opaque_type_origin(def_id, span).is_some();
let value = ty.fold_with(&mut ty::fold::BottomUpFolder {
tcx: self.tcx,
lt_op: |lt| lt,
ct_op: |ct| ct,
ty_op: |ty| match *ty.kind() {
// Closures can't create hidden types for opaque types of their parent, as they
// do not have all the outlives information available. Also `type_of` looks for
// hidden types in the owner (so the closure's parent), so it would not find these
// definitions.
ty::Opaque(def_id, _substs)
if matches!(
self.opaque_type_origin(def_id, span),
Some(OpaqueTyOrigin::FnReturn(..))
) =>
{
let span = if span.is_dummy() { self.tcx.def_span(def_id) } else { span };
let cause = ObligationCause::new(span, body_id, code.clone());
ty::Opaque(def_id, _substs) if replace_opaque_type(def_id) => {
let def_span = self.tcx.def_span(def_id);
let span = if span.contains(def_span) { def_span } else { span };
let code = traits::ObligationCauseCode::OpaqueReturnType(None);
let cause = ObligationCause::new(span, body_id, code);
// FIXME(compiler-errors): We probably should add a new TypeVariableOriginKind
// for opaque types, and then use that kind to fix the spans for type errors
// that we see later on.
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_typeck/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,7 @@ pub(super) fn check_fn<'a, 'tcx>(
fcx.register_infer_ok_obligations(fcx.infcx.replace_opaque_types_with_inference_vars(
declared_ret_ty,
body.value.hir_id,
DUMMY_SP,
traits::ObligationCauseCode::OpaqueReturnType(None),
decl.output.span(),
param_env,
));
// If we replaced declared_ret_ty with infer vars, then we must be infering
Expand Down
118 changes: 59 additions & 59 deletions compiler/rustc_typeck/src/check/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,10 @@ use rustc_hir::lang_items::LangItem;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::LateBoundRegionConversionTime;
use rustc_infer::infer::{InferOk, InferResult};
use rustc_infer::traits::ObligationCauseCode;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::{self, Ty};
use rustc_span::source_map::Span;
use rustc_span::DUMMY_SP;
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::traits::error_reporting::ArgKind;
use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
Expand Down Expand Up @@ -429,14 +427,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// in this binder we are creating.
assert!(!expected_sig.sig.skip_binder().has_vars_bound_above(ty::INNERMOST));
let bound_sig = expected_sig.sig.map_bound(|sig| {
let output = self.hide_parent_opaque_types(
sig.output(),
expected_sig.cause_span.unwrap_or(DUMMY_SP),
body.id().hir_id,
);
self.tcx.mk_fn_sig(
sig.inputs().iter().cloned(),
output,
sig.output(),
sig.c_variadic,
hir::Unsafety::Normal,
Abi::RustCall,
Expand Down Expand Up @@ -608,23 +601,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// function.
Some(hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn)) => {
debug!("closure is async fn body");
self.deduce_future_output_from_obligations(expr_def_id).unwrap_or_else(|| {
// AFAIK, deducing the future output
// always succeeds *except* in error cases
// like #65159. I'd like to return Error
// here, but I can't because I can't
// easily (and locally) prove that we
// *have* reported an
// error. --nikomatsakis
astconv.ty_infer(None, decl.output.span())
})
self.deduce_future_output_from_obligations(expr_def_id, body.id().hir_id)
.unwrap_or_else(|| {
// AFAIK, deducing the future output
// always succeeds *except* in error cases
// like #65159. I'd like to return Error
// here, but I can't because I can't
// easily (and locally) prove that we
// *have* reported an
// error. --nikomatsakis
astconv.ty_infer(None, decl.output.span())
})
}

_ => astconv.ty_infer(None, decl.output.span()),
},
};
let supplied_return =
self.hide_parent_opaque_types(supplied_return, decl.output.span(), body.id().hir_id);

let result = ty::Binder::bind_with_vars(
self.tcx.mk_fn_sig(
Expand All @@ -645,67 +637,75 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
result
}

fn hide_parent_opaque_types(&self, ty: Ty<'tcx>, span: Span, body_id: hir::HirId) -> Ty<'tcx> {
let InferOk { value, obligations } = self.replace_opaque_types_with_inference_vars(
ty,
body_id,
span,
ObligationCauseCode::MiscObligation,
self.param_env,
);
self.register_predicates(obligations);
value
}

/// Invoked when we are translating the generator that results
/// from desugaring an `async fn`. Returns the "sugared" return
/// type of the `async fn` -- that is, the return type that the
/// user specified. The "desugared" return type is an `impl
/// Future<Output = T>`, so we do this by searching through the
/// obligations to extract the `T`.
#[instrument(skip(self), level = "debug")]
fn deduce_future_output_from_obligations(&self, expr_def_id: DefId) -> Option<Ty<'tcx>> {
fn deduce_future_output_from_obligations(
&self,
expr_def_id: DefId,
body_id: hir::HirId,
) -> Option<Ty<'tcx>> {
let ret_coercion = self.ret_coercion.as_ref().unwrap_or_else(|| {
span_bug!(self.tcx.def_span(expr_def_id), "async fn generator outside of a fn")
});

let ret_ty = ret_coercion.borrow().expected_ty();
let ret_ty = self.inh.infcx.shallow_resolve(ret_ty);
let (def_id, substs) = match *ret_ty.kind() {
ty::Opaque(def_id, substs) => (def_id, substs),

let get_future_output = |predicate: ty::Predicate<'tcx>, span| {
// Search for a pending obligation like
//
// `<R as Future>::Output = T`
//
// where R is the return type we are expecting. This type `T`
// will be our output.
let bound_predicate = predicate.kind();
if let ty::PredicateKind::Projection(proj_predicate) = bound_predicate.skip_binder() {
self.deduce_future_output_from_projection(
span,
bound_predicate.rebind(proj_predicate),
)
} else {
None
}
};

let output_ty = match *ret_ty.kind() {
ty::Infer(ty::TyVar(ret_vid)) => {
self.obligations_for_self_ty(ret_vid).find_map(|(_, obligation)| {
get_future_output(obligation.predicate, obligation.cause.span)
})?
}
ty::Opaque(def_id, substs) => self
.tcx
.bound_explicit_item_bounds(def_id)
.transpose_iter()
.map(|e| e.map_bound(|e| *e).transpose_tuple2())
.find_map(|(p, s)| get_future_output(p.subst(self.tcx, substs), s.0))?,
ty::Error(_) => return None,
_ => span_bug!(
self.tcx.def_span(expr_def_id),
"async fn generator return type not an inference variable"
),
};

let item_bounds = self.tcx.bound_explicit_item_bounds(def_id);

// Search for a pending obligation like
//
// `<R as Future>::Output = T`
//
// where R is the return type we are expecting. This type `T`
// will be our output.
let output_ty = item_bounds
.transpose_iter()
.map(|e| e.map_bound(|e| *e).transpose_tuple2())
.find_map(|(predicate, span)| {
let bound_predicate = predicate.subst(self.tcx, substs).kind();
if let ty::PredicateKind::Projection(proj_predicate) = bound_predicate.skip_binder()
{
self.deduce_future_output_from_projection(
span.0,
bound_predicate.rebind(proj_predicate),
)
} else {
None
}
});
// async fn that have opaque types in their return type need to redo the conversion to inference variables
// as they fetch the still opaque version from the signature.
let InferOk { value: output_ty, obligations } = self
.replace_opaque_types_with_inference_vars(
output_ty,
body_id,
self.tcx.def_span(expr_def_id),
self.param_env,
);
self.register_predicates(obligations);

debug!("deduce_future_output_from_obligations: output_ty={:?}", output_ty);
output_ty
Some(output_ty)
}

/// Given a projection like
Expand Down
23 changes: 15 additions & 8 deletions src/librustdoc/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,12 +218,9 @@ pub(crate) struct RenderOptions {
///
/// Be aware: This option can come both from the CLI and from crate attributes!
pub(crate) playground_url: Option<String>,
/// Whether to sort modules alphabetically on a module page instead of using declaration order.
/// `true` by default.
//
// FIXME(misdreavus): the flag name is `--sort-modules-by-appearance` but the meaning is
// inverted once read.
pub(crate) sort_modules_alphabetically: bool,
/// What sorting mode to use for module pages.
/// `ModuleSorting::Alphabetical` by default.
pub(crate) module_sorting: ModuleSorting,
/// List of themes to extend the docs with. Original argument name is included to assist in
/// displaying errors if it fails a theme check.
pub(crate) themes: Vec<StylePath>,
Expand Down Expand Up @@ -281,6 +278,12 @@ pub(crate) struct RenderOptions {
pub(crate) no_emit_shared: bool,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub(crate) enum ModuleSorting {
DeclarationOrder,
Alphabetical,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub(crate) enum EmitType {
Unversioned,
Expand Down Expand Up @@ -650,7 +653,11 @@ impl Options {
let proc_macro_crate = crate_types.contains(&CrateType::ProcMacro);
let playground_url = matches.opt_str("playground-url");
let maybe_sysroot = matches.opt_str("sysroot").map(PathBuf::from);
let sort_modules_alphabetically = !matches.opt_present("sort-modules-by-appearance");
let module_sorting = if matches.opt_present("sort-modules-by-appearance") {
ModuleSorting::DeclarationOrder
} else {
ModuleSorting::Alphabetical
};
let resource_suffix = matches.opt_str("resource-suffix").unwrap_or_default();
let enable_minification = !matches.opt_present("disable-minification");
let markdown_no_toc = matches.opt_present("markdown-no-toc");
Expand Down Expand Up @@ -731,7 +738,7 @@ impl Options {
external_html,
id_map,
playground_url,
sort_modules_alphabetically,
module_sorting,
themes,
extension_css,
extern_html_root_urls,
Expand Down
17 changes: 10 additions & 7 deletions src/librustdoc/html/render/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use super::{
};

use crate::clean::{self, types::ExternalLocation, ExternalCrate};
use crate::config::RenderOptions;
use crate::config::{ModuleSorting, RenderOptions};
use crate::docfs::{DocFS, PathError};
use crate::error::Error;
use crate::formats::cache::Cache;
Expand Down Expand Up @@ -95,7 +95,7 @@ pub(crate) struct SharedContext<'tcx> {
created_dirs: RefCell<FxHashSet<PathBuf>>,
/// This flag indicates whether listings of modules (in the side bar and documentation itself)
/// should be ordered alphabetically or in order of appearance (in the source code).
pub(super) sort_modules_alphabetically: bool,
pub(super) module_sorting: ModuleSorting,
/// Additional CSS files to be added to the generated docs.
pub(crate) style_files: Vec<StylePath>,
/// Suffix to be added on resource files (if suffix is "-v2" then "light.css" becomes
Expand Down Expand Up @@ -280,10 +280,13 @@ impl<'tcx> Context<'tcx> {
}
}

if self.shared.sort_modules_alphabetically {
for items in map.values_mut() {
items.sort();
match self.shared.module_sorting {
ModuleSorting::Alphabetical => {
for items in map.values_mut() {
items.sort();
}
}
ModuleSorting::DeclarationOrder => {}
}
map
}
Expand Down Expand Up @@ -394,7 +397,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
external_html,
id_map,
playground_url,
sort_modules_alphabetically,
module_sorting,
themes: style_files,
default_settings,
extension_css,
Expand Down Expand Up @@ -476,7 +479,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
issue_tracker_base_url,
layout,
created_dirs: Default::default(),
sort_modules_alphabetically,
module_sorting,
style_files,
resource_suffix,
static_root_path,
Expand Down
8 changes: 6 additions & 2 deletions src/librustdoc/html/render/print_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use super::{
AssocItemLink, Context, ImplRenderingParameters,
};
use crate::clean;
use crate::config::ModuleSorting;
use crate::formats::item_type::ItemType;
use crate::formats::{AssocItemRender, Impl, RenderMode};
use crate::html::escape::Escape;
Expand Down Expand Up @@ -246,8 +247,11 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
compare_names(lhs.as_str(), rhs.as_str())
}

if cx.shared.sort_modules_alphabetically {
indices.sort_by(|&i1, &i2| cmp(&items[i1], &items[i2], i1, i2, cx.tcx()));
match cx.shared.module_sorting {
ModuleSorting::Alphabetical => {
indices.sort_by(|&i1, &i2| cmp(&items[i1], &items[i2], i1, i2, cx.tcx()));
}
ModuleSorting::DeclarationOrder => {}
}
// This call is to remove re-export duplicates in cases such as:
//
Expand Down
2 changes: 1 addition & 1 deletion src/librustdoc/json/conversions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum {
AssocTypeItem(t, b) => ItemEnum::AssocType {
generics: t.generics.into_tcx(tcx),
bounds: b.into_iter().map(|x| x.into_tcx(tcx)).collect(),
default: t.item_type.map(|ty| ty.into_tcx(tcx)),
default: Some(t.item_type.unwrap_or(t.type_).into_tcx(tcx)),
},
// `convert_item` early returns `None` for striped items and keywords.
StrippedItem(_) | KeywordItem(_) => unreachable!(),
Expand Down
9 changes: 9 additions & 0 deletions src/test/rustdoc-json/blanket_impls.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Regression test for <https://github.com/rust-lang/rust/issues/98658>

#![no_std]

// @has blanket_impls.json
// @has - "$.index[*][?(@.name=='Error')].kind" \"assoc_type\"
// @has - "$.index[*][?(@.name=='Error')].inner.default.kind" \"resolved_path\"
// @has - "$.index[*][?(@.name=='Error')].inner.default.inner.name" \"Infallible\"
pub struct ForBlanketTryFromImpl;
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ impl Thing for AssocNoCopy {
type Out = Box<dyn Bar<Assoc: Copy>>;

fn func() -> Self::Out {
Box::new(AssocNoCopy)
//~^ ERROR the trait bound `String: Copy` is not satisfied
Box::new(AssocNoCopy)
}
}
Loading