#![no_core] due to how we currently reference lang items.@oli-obk pointed out:
Oh, that's a very good idea. I wonder if we can make
lang_itemsprivate at some point and just have sensible wrappers likerequire_lang_item.
I'm opening this issue to start a discussion about how we could take this forward.
Here are my thoughts at the moment:
tcx.lang_items().<item>().unwrap() as in #![no_core] this is a hard panictcx.require_lang_item(<Item>, span) trivially resolves thistcx.lang_items().<item>() and remove lang_items for the type context's public APIif Some(def_id) == tcx.lang_items().<item>() {
// some smart diagnostic
}
def_id == tcx.require_lang_item(<Item>, span) because we don't want to trigger a fatal error if the lang item isn't found, we just don't want to emit the diagnosticMy feeling at the moment is that something along the lines of tcx.is_lang_item(<Item>, def_id) is the tidiest way to solve this, but obviously this is going to touch a lot of code so I thought it was worth a discussion.
If we want to make it clear that this should only be used for diagnostics, we could name the function check_lang_item_for_diagnostic or sth similar. It's a mouth full, but at least this means noone will mis-use it. Another alternative is to make it a method on DiagnosticBuilder that takes a closure and only invokes the closure if the DefId is the specified lang item. This way it definitely can't be mis-used and is on the right API.
The easiest way might be to add tcx.get_lang_item(LangItem) -> Option<DefId> with a doc comment recommending require_lang_item in case the lang item is required.
I definitely agree that we need to make sure it's not misused, although refactoring this sort of thing
https://github.com/rust-lang/rust/blob/a74d1862d4d87a56244958416fd05976c58ca1a8/src/librustc_trait_selection/traits/error_reporting/mod.rs#L286
https://github.com/rust-lang/rust/blob/a74d1862d4d87a56244958416fd05976c58ca1a8/src/librustc_trait_selection/traits/error_reporting/mod.rs#L410
https://github.com/rust-lang/rust/blob/a74d1862d4d87a56244958416fd05976c58ca1a8/src/librustc_trait_selection/traits/error_reporting/mod.rs#L445
to use a modification like that to the DiagnosticBuilder API might be more trouble than it's worth...
I think we should use a custom return type, not Option, for the result of tcx.lang_items().<item>(). It would have a require method that takes a span and a TyCtxt and works the same way as require_lang_item, plus an exists method that returns a bool. This makes it much harder to misuse the API and you can still match on it to extract the def_id.
The easiest way might be to add
tcx.get_lang_item(LangItem) -> Option<DefId>with a doc comment recommendingrequire_lang_itemin case the lang item is required.
I think we'd have to be careful with this as I imagine this is the sort of thing that will slip through almost all code reviews
I think we should use a custom return type, not
Option, for the result oftcx.lang_items().<item(>). It would have arequiremethod that takes a span and works the same way asrequire_lang_itemand an exists method that converts to abool. This makes it much harder to misuse the API.
I really like this idea - although to make sure lang_items stays private, we'd probably want to move it up a level. Something like tcx.query_lang_item(<Item>) that returns the new opaque option.
We could just bolt a is_def_id(def_id) method on the API for the opaque option then as well to deal with the diagnostic pattern.
to use a modification like that to the DiagnosticBuilder API might be more trouble than it's worth...
Oh wow... that !is_unsize definitely kills that idea, agreed.
I really like this idea - although to make sure
lang_itemsstays private, we'd probably want to move it up a level. Something liketcx.query_lang_item(<Item>)that returns the new opaque option.
I think the suggested idea is to make the LangItems type's functions all private, so we don't need to make lang_items private, as we can just add the is and expect functions to it as public functions and expose no further API
Ahh okay I misunderstood... So the change would be something like:
lang_items API to return the new wrapper in place of the old optionsis and expect methods for the new wrappertcx.require_lang_item to use the new APISome(def_id) == ... pattern to use isI think the suggested idea is to make the LangItems type's functions all private, so we don't need to make lang_items private,
That's what I had in mind, yes. I like avoiding the need for imports (e.g., FutureTraitLangItem) when possible.
Okay yeah - I really like that, I'll have a go at implementing it then
@rustbot claim
(Side note: discussing on the issue seems fine, but this seems like an MCP-worthy thing.)
@nikomatsakis I spoke to @oli-obk about whether an MCP was necessary before I opened this issue but I don鈥檛 think either of us appreciated the amount of code this was going to effect and therefore didn鈥檛 think it was necessary. I don鈥檛 really know anything about the MCP process as I鈥檝e been out of the loop for a while but I鈥檓 more than happy to learn about it and take this down that route.
Triage: Hi, are you still working on this issue @doctorn?
@rustbot release-assignment