|
|
@@ -49,15 +49,16 @@ auto LookupMatchesImpl(Context& context, SemIR::LocId loc_id,
|
|
|
|
|
|
// The result of EvalLookupSingleImplWitness(). It can be one of:
|
|
|
// - No value. Lookup failed to find an impl declaration.
|
|
|
-// - A concrete value. Lookup found a concrete impl declaration that can be
|
|
|
-// used definitively.
|
|
|
-// - A symbolic value. Lookup found an impl but it is not returned since lookup
|
|
|
-// will need to be done again with a more specific query to look for
|
|
|
-// specializations.
|
|
|
+// - An effectively final value. Lookup found either a concrete impl or a
|
|
|
+// `final` impl declaration; both can be used definitely. A witness is
|
|
|
+// available.
|
|
|
+// - A non-`final` symbolic value. Lookup found an impl, but it is not returned
|
|
|
+// since lookup will need to be done again with a more specific query to look
|
|
|
+// for specializations.
|
|
|
class [[nodiscard]] EvalImplLookupResult {
|
|
|
public:
|
|
|
static auto MakeNone() -> EvalImplLookupResult {
|
|
|
- return EvalImplLookupResult(SemIR::InstId::None);
|
|
|
+ return EvalImplLookupResult(FoundNone());
|
|
|
}
|
|
|
static auto MakeFinal(SemIR::InstId inst_id) -> EvalImplLookupResult {
|
|
|
return EvalImplLookupResult(inst_id);
|
|
|
@@ -66,35 +67,33 @@ class [[nodiscard]] EvalImplLookupResult {
|
|
|
return EvalImplLookupResult(FoundNonFinalImpl());
|
|
|
}
|
|
|
|
|
|
- // True if a concrete impl witness was found or a non-final impl. In the
|
|
|
- // latter case the InstId of the impl's witness is not returned, only the fact
|
|
|
- // that it exists.
|
|
|
+ // True if an impl declaration was found, either effectively final or
|
|
|
+ // symbolic.
|
|
|
auto has_value() const -> bool {
|
|
|
- return std::holds_alternative<FoundNonFinalImpl>(result_) ||
|
|
|
- std::get<SemIR::InstId>(result_).has_value();
|
|
|
+ return !std::holds_alternative<FoundNone>(value_);
|
|
|
}
|
|
|
|
|
|
- // True if there is a concrete witness in the result. If false, and
|
|
|
- // `has_value()` is true, it means a non-final impl was found and a further
|
|
|
- // more specific query will need to be done.
|
|
|
- auto has_concrete_value() const -> bool {
|
|
|
- const auto* inst_id = std::get_if<SemIR::InstId>(&result_);
|
|
|
- return inst_id && inst_id->has_value();
|
|
|
+ // True if there is an effectively final witness in the result. If false, and
|
|
|
+ // `has_value()` is true, it means an impl was found that's not effectively
|
|
|
+ // final, and a further more specific query will need to be done.
|
|
|
+ auto has_final_value() const -> bool {
|
|
|
+ return std::holds_alternative<SemIR::InstId>(value_);
|
|
|
}
|
|
|
|
|
|
- // Only valid if `has_concrete_value()` is true. Returns the witness id for
|
|
|
- // the found impl declaration, or None if `has_value()` is false.
|
|
|
- auto concrete_witness() const -> SemIR::InstId {
|
|
|
- return std::get<SemIR::InstId>(result_);
|
|
|
+ // Returns the witness id for an effectively final value's impl declaration.
|
|
|
+ // Only valid to call if `has_final_value` is true.
|
|
|
+ auto final_witness() const -> SemIR::InstId {
|
|
|
+ return std::get<SemIR::InstId>(value_);
|
|
|
}
|
|
|
|
|
|
private:
|
|
|
+ struct FoundNone {};
|
|
|
struct FoundNonFinalImpl {};
|
|
|
+ using Value = std::variant<SemIR::InstId, FoundNone, FoundNonFinalImpl>;
|
|
|
|
|
|
- explicit EvalImplLookupResult(SemIR::InstId inst_id) : result_(inst_id) {}
|
|
|
- explicit EvalImplLookupResult(FoundNonFinalImpl f) : result_(f) {}
|
|
|
+ explicit EvalImplLookupResult(Value value) : value_(value) {}
|
|
|
|
|
|
- std::variant<SemIR::InstId, FoundNonFinalImpl> result_;
|
|
|
+ Value value_;
|
|
|
};
|
|
|
|
|
|
// Looks for a witness instruction of an impl declaration for a query consisting
|
|
|
@@ -102,10 +101,13 @@ class [[nodiscard]] EvalImplLookupResult {
|
|
|
// execute lookup via the LookupImplWitness instruction. It does not consider
|
|
|
// the self facet value for finding a witness, since LookupImplWitness() would
|
|
|
// have found that and not caused us to defer lookup to here.
|
|
|
+//
|
|
|
+// `poison_final_results` poisons lookup results which are effectively final,
|
|
|
+// preventing overlapping final impls.
|
|
|
auto EvalLookupSingleImplWitness(Context& context, SemIR::LocId loc_id,
|
|
|
SemIR::LookupImplWitness eval_query,
|
|
|
SemIR::InstId self_facet_value_inst_id,
|
|
|
- bool poison_concrete_results)
|
|
|
+ bool poison_final_results)
|
|
|
-> EvalImplLookupResult;
|
|
|
|
|
|
} // namespace Carbon::Check
|